Notes on C

Notes on C

October 3, 2021

1 Arrays and pointers

It is important to realize that an array is different from a pointer, although both can
be of the same type. When we write

int a[10], *p;

then both a and p are of type pointer-to-int, but writing

a = p; // wrong!

would be wrong, as a always refers to a fixed address that cannot be changed. On
the other hand, this is correct:

p = a;

Since p is a pointer we can assign an address to it. We say that p is an lvalue
whereas a is not.

The address assigned to p is actually the address of a[0] so the following
assignment has exactly the same meaning:

p = &a[0];

Assignment is not the same as initialization. These are both wrong:

a = {1, 2, 3}; // wrong! 
p = {4, 5, 6}; // wrong!

The following definition with initialization is fine:

int a[10] = {1, 2, 3};

The first three array elements are assigned and all other elements are set to zero
due to the ininitialization. Without initialization the value of each element would
have been undefined.

We cannot initialize over a pointer:

int *p = {1, 2, 3}; // wrong!

But note that this is perfectly fine:

char *q = Beatrice;

Assignment over a pointer is possible after we have made it point to an address:

int a[10], *p; 
p = a; // point to array 
p[0] = 1; // equivalent to *p = 1 
p[1] = 2;

2 String allocation and assignment

Strings stored in character arrays are terminated by a zero. So to store a five
character string we need a six element character array.

char str[6];

We need to take this into account when allocating a pointer:

p = (char *)malloc(strlen(str) + 1); // add 1 
strcpy(p, str);

Since the character array is not an lvalue we cannot do this:

str = Dante; // wrong, no lvalue

We need to do this instead:

strcpy(str, Dante);

or properly initialize the array:

char str[6] = Dante;

The compiler now fills the array with the string being kept in memory, which is
somewhat wasteful. If we want to keep the string unchanged we can use a constant
pointer like this:

const char *const pstr = Dante;

The first const disallows us to change the characters.

strcpy(pstr, Paolo); // not allowed

The second const disallows us to reassign the pointer.

pstr = NULL; // not allowed 
pstr = Paolo; // not allowed