• Advertisement
Sign in to follow this  

difference between char *array[5] and char **array

This topic is 4764 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi to everyone and happy new year. I'm studying C at the moment and try to wipe out all my questions about pointers. Say we have the following piece of code.
char **array1;
char *array2[5];

array1 = malloc(5 * sizeof(char));
array1[0] = "blabla";
array1[1] = "more blabla";
...
array2[0] = "even more babbling";
...etc.
Is there any difference in the memory layout of the two variables? Are they accessed the same way? I mean the expression
*(*(array + 1))
*(*(array1 + 1))
accesses the 1st character of the second row in both arrays. Do you know any resource where I could read more about pointer arrays and multidimensional pointers? Thanks for your time :)

Share this post


Link to post
Share on other sites
Advertisement
Ok, I'll explain the second one first. char* array2[5] declares an array of 5 char* pointers. The size of each element in array2 depends on the machine you are programming. On x86 (32-bit) systems, the size of each element would be 4 bytes.

An example for how to use this array is given below:


char* array2[5];
char a = 50;
char b = 100;

array2[0] = &a;
array2[1] = &b;





At the end of the above example, the first element of array2 (at index 0) would store the address of the char 'a'. Similarly, the second element of array2 would store the address of the char 'b'.

If you need an array of chars to represent a string, then you would use:

char myString[20] = "Hello World";

This would declare an array of 20 chars and initialize 12 elements of the array: 11 for the values of each character plus a null termination value of 0 will be stored in the 12th element of the array (at index 11).

char **array1 declares a pointer to a pointer to a char. Be careful though because in its current state, it is uninitialized. This means that it could be pointing to any random data. To be safe, always initialize your pointers as early as possible (preferably at declaration). You can always set pointers to 0 to specify that the pointer is NULL (it doesn't point to anything).

To use pointers to pointers, you could do the following:

char a = 20;
char* b = &a;
char** c = &b;

To access the value of 'a' via 'c' you can use the expression **c. This would dereference the pointer 'c' twice, hence ending back at 'a'.

Pointers to pointers can be handy if you are working with multiple arrays (or a multi-dimensional array).

Good luck with your studies,

James Bird.

[Edited by - birdjames on January 3, 2005 11:24:32 AM]

Share this post


Link to post
Share on other sites
So by doing

array1 = malloc(5 * sizeof(char));

the array1 pointer is pointing to a pointer array of size 5? (instead of a single pointer) And as the name of (or maybe address?) of an array is a pointer this is valid?

Share this post


Link to post
Share on other sites
Quote:
Original post by moucard
So by doing

array1 = malloc(5 * sizeof(char));

the array1 pointer is pointing to a pointer array of size 5? (instead of a single pointer) And as the name of (or maybe address?) of an array is a pointer this is valid?
No, what you did there was incorrect.
The two stars means that it is a pointer to a pointer.
So you must first allocate an array of pointers:
array1 = malloc(5 * sizeof(char*));
Then, the lines you followed that with were not copying the strings into it, it was merely putting the address of the static data into it. What you probably want is:
for (int i=0; i<5; ++i)
array1[i] = malloc(32 * sizeof(char));
(Where 32 is the maximum length needed for the longest of the strings)
Now you can do this to copy those strings into it:
strcpy(array1[0], "blabla");
strcpy(array1[1], "more blabla");
...
Then when you're done with it you clean up like this:
for (int i=0; i<5; ++i)
free(array1[i]);
free(array1);
array1 = NULL;


Quote:
*(*(array1 + 1))
That is incorrect also. You are starting with a pointer to a pointer, then incrementing the pointer (it's no longer pointing to anything useful), then getting what that random memory location points to, then getting whatever that random memory location points to, which will be utter garbage, or an access violation.
The first character of the second string can be accessed from the expression:
array1[1][0]
where 1 is the second row, and the 0 is the first character.

Hope that helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by moucard
Is there any difference in the memory layout of the two variables?


I don't think I'd be able to explain the rest any better, but I don't think this has been answered yet.

There are generally two distinct memory spaces: the stack and the heap (or sometimes several heaps in more complex apps)

This will allocate the memory on the stack:

char charArray[5];


and this will allocate it on the heap:

char * charArray = (char*)malloc(5 * sizeof(char));


Both are used in exactly the same way, but the stack and the heap are quite seperate areas of memory and used for different things. The stack is the home of variables whose lifetimes are controlled by the compiler - they are implicitly allocated while they are in scope. The heap is the home of variables whose lifetimes are controlled by the application - they are allocated explicitly by the programmer (using new, malloc() or something similar) and explicitly deallocated by the programmer when they are no longer needed.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement