Let us say we have a array of pointers:
char *ptr[30];
Now this works fine, and doesn\'t seems to do anything unexpected! I can input names easi
If you use what is in your example, you just owerwrite other locations what come after your ptr
array. Most compilers should actually give at least a warning. Your program would crash on most systems, you were just very lucky.
You've allocated space for 30 pointers, but you haven't initialized them to point anywhere meaningful. Unless you declared the array outside of a function, each element in the array will contain some random bit string that may or may not correspond to a writable memory location. If we drew a picture, it would look something like this (all addresses are pulled out of thin air; don't assume this corresponds to any real architecture):
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- ptr 0xbbc81230 0x?? 0x?? 0x?? 0x?? 0xbbc81234 0x?? 0x?? 0x?? 0x?? 0xbbc81238 0x?? 0x?? 0x?? 0x?? ... 0xbbc812a8 0x?? 0x?? 0x?? 0x??
where 0x??
represents a random byte value. For the behavior you've described, each of the random values just happens to point to writable memory, and writing over whatever's stored there just happens to not have any immediate ill effects.
Bad juju: it looks like your code is working properly when in reality it's behaving very badly, and can lead to some nasty runtime problems elsewhere in your program that's a pain to debug.
You will need to explicitly set each element of the ptr
array to point to a valid memory location before attempting to write through it.
Suppose we add the following code:
ptr[0] = malloc(strlen("foo") + 1);
strcpy(ptr[0], "foo");
ptr[1] = malloc(strlen("bar") + 1);
strcpy(ptr[1], "bar");
We've dynamically allocated some extra memory to hold a couple of strings, and stored the pointers to those new buffers to ptr[0]
and ptr[1]
.
Our picture would now look something like this:
Item Address 0x00 0x01 0x02 0x03 ---- ------- ---- ---- ---- ---- 0x80ff0000 'f' 'o' 'o' 0x00 ... 0x80ffcdc0 'b' 'a' 'r' 0x00 ... ptr 0xbbc81230 0x80 0xff 0x00 0x00 0xbbc81234 0x80 0xff 0xcd 0xc0 0xbbc81238 0x?? 0x?? 0x?? 0x?? ... 0xbbc812a8 0x?? 0x?? 0x?? 0x??
ptr[0]
now contains the address of a buffer sized to hold 4 char
values, and we copy the string "foo" to that buffer. Similarly, ptr[1]
contains the address of another 4-byte buffer that now contains the string "bar".
When you define a pointer like:
char *ptr = 0; // NULL pointer: dereferencing it will crash
puts(ptr); // crash
You merely create a link to a place in memory:
ptr = "string"; // dereferencing it will show the string
puts(ptr); // displaying "string"
So having an array of pointers merely creates a list of references to other variables.
To reference a place in memory, you then have to assign variables to your pointers, or allocate memory for each pointer.
The pointer cannot be used that way. It might "work" for you sometimes by sheer chance, but using a pointer without allocating memory for it will cause undefined behavior - meaning that your program may behave erratically and give you unexpected results.
Remember, just because your program compiles and runs doesn't mean it is correct. In the C language there is a whole class of errors known as "undefined behavior", many of which the compiler will happily let you do without complaining. These include overwriting a buffer, using an uninitialized variable, or dereferencing a pointer that doesn't point to a legitimately allocated memory block. Programs that exhibit undefined behavior may even appear to work normally sometimes - but they are usually very unstable and prone to crash.