Advanced C topics – Part1

I just want to touch in this post some of the things which are generally considered to be advanced C topics. I am referring here to things like: differences between pointers and arrays, arrays passed as parameters and returned as value from functions, and pointers to functions.

Can we pass an array as a function parameter in C language? Isn’t quite strange when we see in C programs something like this:

void function (int a[], int n);

How can one pass an entire array as a parameter to a function? How many parameters does the corresponding function accept, two or many?
The answer is quite straightforward: you are passing in fact just an address as a parameter. This is a pointer to the first element of the array. It is the old discussion about different ways of how to refer to an array or to an element of it (if you define it like this int a[] you can refer to it like this int *a; and refer to its elements with *(a+2) – third element in the array; or you can refer like this a[2] – 3’rd element).
Please be aware when passing arrays not to overflow the stack. This is the danger that arrays passed as parameters may involve: compiler never knows how big the array will be, because it will replace the array declaration with a pointer so it will reserve space just for a pointer.

Actually when defining an array the compiler automatically generates a pointer to its first element, it is something like this:


void function (int &a[0], int n);

Or, more commonly

void function (int *a, int n);

Please pay attention that the parameter is transferred by pointer meaning that any changes made inside the function will directly affect array’s elements and not copies of them.

By the way, which is the difference between following notations?

int *a[10]; //this is an array of 10 pointers
int (*a)[10]; //parenthesis have higher priority >> pointer to an array of 10 integers

The conclusion up to now would be that pointers and arrays act pretty much in the same way. Well, this is not quite true. The big difference comes from the fact that when declaring an array you actually ask the for a certain storage.

char a[] = “George”; // I need a space where I want to put characters ‘G’ ‘e’ ‘o’ ‘r’ ‘g’ ‘e’ plus NUL
char *a = “George”; // I declare just a pointer to a constant string of characters

Actually I have to explicitly specify that I want that string to be constant otherwise a pointer can be changed to point somewhere else. I can do something like this

*a = “John”;

Also when using pointers to characters usually you won’t have the possibility to change the value of characters pointed. Somehow the string that a points to is read-only.


*(a+1) = ‘o’; // will be flagged as an error instead of replacing George with Goorge
// data pointed to can be placed in a non-volatile memory, so it cannot be changed

It is rather indicated that pointer to characters should be written in the following manner:


const char *a = “George”;
*a = “John”; // will be flagged as an error

On the other hand character arrays even if they have the advantage of being writable, they cannot be re-sized. Once an array has been declared having a certain length, its size cannot be changed.

char *a = “John”;
char b[4];

John” string cannot fit into b[] because this character array does not have enough room for the trailing NUL character.

Another difference between pointers and arrays is that pointers can be operated in the same way that the variables are. Can be subtracted or assigned. You cannot do same thing with arrays:

char a[] = “George”;
char b[] = “Greg”;
b[] = a[]; // this will be flagged as an error

Please pay attention to the fact that this rule (of deriving a pointer from an array name) does not apply recursively. In case you have a bi-dimensional array (an array of an array) this is still translated by the compiler as a pointer to an array and not a pointer to a pointer.

Let’s just consider a bi-dimensional matrix like:

int a[5][7];

If you want to pass this as a parameter to a function for whatever reason you will write something like this (the most straightforward way):

func (int a[5][7])
{
...
}

But this is considered in C as an array of multiple arrays, just as we already agreed upon. In other words this is an array of 5 elements, each one being on its turn an array of 7 elements. Basically the dimension of the big array is 5, so can write it like this:

func (int a[][7])
{
...
}

As we discussed previously the function doesn’t have to know the dimension of the array, so it can simply be replaced by what is above. An array is implicitly a pointer
so this is equivalent to:

func (int (*a)[7])
{
...
}

Some programmers are often fooled by this and, as I said, use to pass bi-dimensional arrays as pointers to pointers, writing something like this:

func (int **a)
{
...
} // this will generate a compile-time error

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: