Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to Array vs reference to array pointer

Tags:

arrays

c

pointers

void check(void* elemAddr){
    char* word = *((char**)elemAddr);
    printf("word is %s\n",word);
}

int main(){
    char array[10] = {'j','o','h','n'};
    char * bla = array;
    check(&bla);
    check(&array);
}

Output:

word is john

RUN FINISHED; Segmentation fault; core dumped;

First one works, but second not. I don't understand why this happens.

like image 826
Ioane Sharvadze Avatar asked Jan 03 '15 13:01

Ioane Sharvadze


People also ask

What is difference between array to pointer and pointer to array?

Here is a list of the differences present between Pointer to an Array and Array of Pointers. A user creates a pointer for storing the address of any given array. A user creates an array of pointers that basically acts as an array of multiple pointer variables. It is alternatively known as an array pointer.

How do you reference an array pointer?

A pointer can point to an array of variables. To access an array element, use operator []. Array indices begin with 0. If pointer points to array, it means that it points to the first variable in the array (the following two expressions are true: arr == &arr[0] and *arr == arr[0] ).

What is a reference to an array?

Reference to an array means aliasing an array while retaining its identity. Reference to an array will not be an int* but an int[].

What is the difference between array and pointer?

An array is a collection of elements of similar data type whereas the pointer is a variable that stores the address of another variable. An array size decides the number of variables it can store whereas; a pointer variable can store the address of only one variable in it.


1 Answers

The problem is, when we do &array, we are getting a char (*)[10] from an char [10], instead of a char **.

Before we do our experiment, I will emphasize that, when we pass an array as an argument to a function, C actually casts the array to a pointer. The big bucket of data is not copied.

Thus, int main(int argc, char **argv) is identical to int main(int argc, char *argv[]) in C.

This made it available for us to print the address of an array with a simple printf.

Let's do the experiment:

char array[] = "john";
printf("array:  %p\n", array);
printf("&array: %p\n", &array);

// Output:
array:  0x7fff924eaae0
&array: 0x7fff924eaae0

After knowing this, let's dig into your code:

char array[10] = "john";
char *bla = array;
check(&bla);
check(&array);

bla is char *, and &bla is char **.

However, array is char [10], and &array is char (*)[10] instead of char **.

So when you pass &array as an argument, char (*)[10] acts like a char * when passing as an argument, as is said above.

Therefore **(char **) &bla == 'j' while *(char *) &array == 'j'. Do some simple experiments and you will prove it.

And you are casting void *elemAddr to a char ** and try to deference it. This will only work with &bla since it is char **. &array will cause a segfault because "john" is interpreted as an address as you do the cast.

like image 76
Star Brilliant Avatar answered Oct 11 '22 19:10

Star Brilliant