C-Programming
 Addresses, Pointers, Structures, Type-casts
  Part 1

My son is studying some energy stuff and the students get a lot of knowledge base with some emphasis of their professors. Among others they also have lessons in computer science. Starting with his second term I am wondering, how a professor can teach them object-oriented programming in C++ without his students having understood the concept of addresses and pointers in C? With this article I am trying to fill the gap.

Introduction

After a short while of writing C-programs you more or less involuntarily come across the issue of pointers. Basically it starts with the address of data in the memory and a new type of variable holding this address and not the data. The variable holding the address in the memory is called pointer, because it points to that address.

And before I really start, I would like to draw your attention to the colophone. I am doing  a few things in peculiar ways, but I have very good reasons to do them this way. In the colophone I am going to explain the why and how. If necessary, each of my articles will get such a section.

My environment

Before I start, I need to describe the environment I am working on:

  • I am doing my daily work on my laptop (A lenovo E555) with Mageia 5 (a Linux derivative) on it.
  • Whenever I intend to mess around with a system, I do this on a virtual machine.
    So I installed VirtualBox on it and run a FreeBSD 10.2 as guest.
  • On this FreeBSD-Guest I have
    • llvm with clang as my C-compiler
    • gdb as my debugger
    • and I am writing my code with vi, because I am toucht yping,
      and prior to debugging or publishing any code, I use the
      set number directive
    • I am using make to compile my programs

This is it basically and this is a part reasons, why the code I present here looks the way it does.
So if you want to reproduce step by step what I am showing here and you are working with an MS-Windows system, I warmly recommend to get cygwin installed on your Windows.

An address and a pointer (the first code)

You may obtain a copy of the following sources here.

So when you have variable and want to know its address in the memory space you yield this address by preceding the variable name with an ampersand:

  1 /*
  2  *1111111112222222222333333333344444444445555555555666666666677777777778
  3  *1234567890123456789012345678901234567890123456789012345678901234567890
  4  */
  5 #include <stdio.h>
  6
  7 int main (void)
  8 {
  9     int mynumber = 0;
 10     int *p_mynumber = NULL;
 11
 12     p_mynumber = &mynumber; /*
 13                              * assignes the address of
 14                              * mynumber to p_mynumber
 15                              */
 16
 17     (void) printf("The address is %#x\n", &mynumber);
 18     (void) printf("The address is %#x\n", p_mynumber);
 19     (void) printf("The value is %d\n", mynumber);
 20     (void) printf("The value is %d\n", *p_mynumber);
 21
 22     mynumber++;
 23
 24     (void) printf("The value is %d\n", mynumber);
 25     (void) printf("The value is %d\n", *p_mynumber);
 26
 27     (*p_mynumber)++;
 28
 29     (void) printf("The value is %d\n", mynumber);
 30     (void) printf("The value is %d\n", *p_mynumber);
 31
 32     return 0;
 33 }

To get this compiled with a makefile, you need to start messing around with make.
Here, you’ll find the book.

Since the program is simple, my makefile also will be fairly simple. Some choose to name their makefile Makefile, but I go with the lower case writing. I will not discuss make and makefiles into deep here, but I may loose a few words on it later.

At this point, we are entering the phase, where we start to understand what we are doing, respectively, where I am explaining the things, that already should be understood.
From the very start to the executable binary we have several steps to do, before we end up with an executable file – the binary.

  1. Write the C-code (I assume you write it without error)
  2. preprocess the C-code (Preprocessor)
  3. translate the code to assembly language (Compiler)
  4. translate the assembly language to object code (Assembler)
  5. link the object code to the final program (Linker)
  6. execute the program

And there are many things to consider, even if we write a simple program like the one in this article. But let’s assume, that our programs will become more complex over the time. Hence it is worth the effort to start in a well organized manner.

Here is the makefile I am using to compile this source:
(Please DON’T copy the text of the makefile from the web-browser, but use the tar-file, I am providing here)

  1 # 
  2 #11111111112222222222333333333344444444445555555555666666666677777777778
  3 #01234567890123456789012345678901234567890123456789012345678901234567890
  4 #
  5
  6 ########################################################################
  7 #
  8 # The tools used
  9 #
 10
 11 CC = /usr/bin/cc
 12
 13 ########################################################################
 14 #
 15 # The parameters passed to the compiler
 16 #
 17
 18 CFLAGS1 = -g -Wno-format
 19 CFLAGS2 = -o
 20 
 21 ########################################################################
 22 #
 23 # The sources
 24 # 
 25 
 26 SRCS = ${HOME}/c-programming/ptr-01/ptr-01.c
 27 
 28 ########################################################################
 29 #
 30 # And finally we are doing things
 31 # 
 32 
 33 ptr-01 :
 34         ${CC}    ${CFLAGS1}     ${CFLAGS2}     $@     ${SRCS}
 35
 36 clean :
 37         rm ptr-01

Now we only need to issue the following command on the command line:

make ptr-01
$ ls -l
total 16
-rw-r--r--  1 yael  yael   586 Mar 25 17:34 makefile
-rwxr-xr-x  1 yael  yael  5598 Mar 25 17:34 ptr-01
-rw-r--r--  1 yael  yael   297 Mar 25 16:32 ptr-01.c
$ ./ptr-01
The address is 0xbfbfec98
The address is 0xbfbfec98
The value is 0
The value is 0
The value is 1
The value is 1
The value is 2
The value is 2
$

But this isn’t everything. I never really trust a program, so I may want to look into it. This is why I compiled the code with the “-g” option. Next I will run it using a debugger.
Here I am using gdb (the GNU Debugger). You’ll find the documentation here.

$ gdb ptr-01
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...
(gdb) b 12
Breakpoint 1 at 0x80485b5: file /home/yael/c-programming/ptr-01/ptr-01.c, line 12.
(gdb) run
Starting program: /home/yael/c-programming/ptr-01/ptr-01 

Breakpoint 1, main () at /home/yael/c-programming/ptr-01/ptr-01.c:12
12 p_mynumber = &mynumber; /*
Current language: auto; currently minimal
(gdb) print &mynumber
$1 = (int *) 0xbfbfec68
(gdb) print mynumber
$2 = 0
(gdb) print p_mynumber
$3 = (int *) 0x0
(gdb) s 
17 (void) printf("The address is %#x\n", &mynumber);
(gdb) print p_mynumber
$4 = (int *) 0xbfbfec68
(gdb) print *p_mynumber
$5 = 0
(gdb) n
The address is 0xbfbfec68
18 (void) printf("The address is %#x\n", p_mynumber);
(gdb) 
The address is 0xbfbfec68
19 (void) printf("The value is %d\n", mynumber);
(gdb) 
The value is 0
20 (void) printf("The value is %d\n", *p_mynumber);
(gdb) 
The value is 0
22 mynumber++;
(gdb) 
24 (void) printf("The value is %d\n", mynumber);
(gdb) print mynumber
$6 = 1
(gdb) 
The value is 1
25 (void) printf("The value is %d\n", *p_mynumber);
(gdb) 
The value is 1
27 (*p_mynumber)++;
(gdb) 
29 (void) printf("The value is %d\n", mynumber);
(gdb) print mynumber
$7 = 2
(gdb) n
The value is 2
30 (void) printf("The value is %d\n", *p_mynumber);
(gdb) 
The value is 2
32 return 0;
(gdb) 
0x080484da in _start1 ()
(gdb) 
Single stepping until exit from function _start1, 
which has no line number information.

Program exited normally.
(gdb) quit
$ 

With the directive “b 12” I am setting a breakpoint at line 12

 11
 12     p_mynumber = &mynumber; /*
 13                              * assignes the address of
 14                              * mynumber to p_mynumber
 15                              */

And then I run the program issueing the debugger directive “run”.
The debugger executes the code in line number 12 and stops.
Now I am checking the content of the pointer and the address of  the variable mynumber (print p_mynumber and print &mynumber)

Then I continue single-stepping the using “s” (step) and “n” (next) to tell the debugger to execute the next instruction and the two following printf() commands print the same addresses to stdout as I checked before .

And this is it.

Colophone

I have already explained at the beginning, that I am touch typing. The vi-editor is the ideal editor for people like me. So I am taking my ground position with the two thumbs resting above the space-key while the other four fingers of the left hand are positioned over the keys asdf and the other four fingers of the right hand are positioned over the keys jklö (I am using a QERTZ-keymapping). From here I am reaching any other key blindly. Well, it’s a matter of practice. The vi-editor supports this technique ideally. The only key out of order is the [ESC]-key and on a QUERTZ-keyboard, I need the [AltGr]-key to access {[]}\ but one can get used to it. When I am writing a lot of code, I am changing my keymapping to QERTY, because then {[]}\ are much easier to reach and I can even type my C-code blindly.
Furthermore I am using a lenovo E555 laptop. This comes with a so called trackpoint, which allows me keep my fingers in the ground position while moving the mouse pointer. Furthermore, I reach the mouse-keys with my thumbs. So I have no need to grab a mouse. My hands stay rested on the keyboard.

And then I did a few goofy things in my code sample. It starts with this:

  1 /*
  2  *1111111112222222222333333333344444444445555555555666666666677777777778
  3  *1234567890123456789012345678901234567890123456789012345678901234567890
  4  */

I am doing this, because I am a system programmer, who also worked a lot with VT-terminals. Though in my early days I had a luxurious 19″ X-Terminal with a resolution of 1280×1024 I always wrote my code to be read on a VT-220 console terminal. And this means 80 columns per line respectively 80 characters per line.  There is a copy/paste error getting text from the xterm to this editor which fits the purpose excellently. When I  set the “set number” directive in my vi-editor, it prints the line numbers and it uses eight (8) columns for this. Next I need 2 columns for the way I make my comments in C and I end up with a remaining 70 columns to write these two lines with numbers. In case I accidentally change the shape of my xterm-window, I can easily re-size it to its originally intended width of 80 characters. copy/past to a fully graphic editor, like the one in my firefox-browser, using the X-buffer has its troubles with blanks and it looses them.  So I need to reformat the C-code and I end up with a much smaller column of line numbers. And this fits exactly to the representation of this article once published. There won’t be a horizontal scrollbar, because the resulting source code fits exactly into that frame.

And then the makefile. A makefile needs tabs instead of blanks in particular places. It’s been a while since I wrote my last bigger makefile and I am no longer fluent with it. So writing the makefile I made a compromise using too many tabs. Nevertheless it works and unless you know it better, just use the makefiles I am providing with the tar-file you can download using the here-links in this article.

The Soundtrack

Without music I can’t do this, so here is the music I am listening to, while writing this article:

Solid Steel 2016/03/25 – Kaytronic
Solid Steel 2016/03/25 – BFDM