Chapter 4. The Shocking Truth: C Arrays and Pointers Are NOT the Same! Should array indices start at 0 or 1? My compromise of 0.5 was rejected without, I thought, proper consideration. —Stan Kelly-Bootle Arrays Are NOT Pointers! The ANSI C Standard paragraph 6.5.4.2 recommends that you Note the distinction between the declarations: extern int *x; extern int y[]; The first declares x to be a pointer to int; the second declares y to be an array of int of unspecified size (an incomplete type), the storage for which is defined elsewhere. Why Doesn't My Code Work? file 1: int mango[100]; file 2: extern int *mango; ... /* some code that references mango[i] */ Here, file 1 defines mango as an array, but file 2 declares it as a pointer. But what is wrong with this? After all, "everybody knows" arrays and pointers are pretty much the same in C. The problem is that "everybody" is wrong! It is like confusing integers and floats: file 1: int guava; file 2: extern float guava; What's a Declaration? What's a Definition?
A definition is the special kind of declaration that creates an object; a declaration indicates a name that allows you to refer to an object created here or elsewhere. Let's review the terminology: definition occurs in only one place specifies the type of an object; reserves storage for it; is used to create new objects example: int my_array[100]; declaration can occur multiple times describes the type of an object; is used to refer to objects defined elsewhere (e.g., in another file) example: extern int my_array[]; The declaration of an external object tells the compiler the type and name of the object, and that memory allocation is done somewhere else. Since you aren't allocating memory for the array at this point, you don't need to provide information on how big it is in total. You do have to provide the size of all array dimensions except the leftmost one—this gives the compiler enough information to generate indexing code. Distinguishing a Definition from a Declaration You can tell these two apart by remembering: A declaration is like a customs declaration: it is not the thing itself, merely a description of some baggage that you say you have around somewhere. a definition is the special kind of declaration that fixes the storage for an object How Arrays and Pointers Are Accessed Contrast the access char * p = "abcdefgh"; ... p[3] with char a[] = "abcdefgh"; ... a[3] They both get you a character 'd' but they get there by very different look-ups. To the p pointe,the compiler emits code to: 1. Get the address that p represents, and retrieve the pointer there. 2. Add the offset that the subscript represents onto the pointer value. 3. Access the byte at the resulting address. Match Your Declarations to the Definition The problem of the external declaration of a pointer not matching the definition of an array is simple to fix—change the declaration so it does match the definition, like this: file 1: int mango[100]; file 2: extern int mango[]; ... /* some code that references mango[i] */ The array definition of mango allocates space for 100 integers. In contrast, the pointer definition: int *raisin; requests a place that holds a pointer. The pointer is to be known by the name raisin, and can point to any int (or array of int) anywhere. The variable raisin itself will always be at the same address, but its contents can change to point to many different ints at different times. Each of those different ints can have different values. The array mango can't move around to different places. At different times it can be filled with different values, but it always refers to the same 100 consecutive memory locations. Other Differences Between Arrays and Pointers
Another way of looking at the differences between arrays and pointers is to compare some of their characteristics, as in Table 4-1. Both arrays and pointers can be initialized with a literal string in their definition. Although these cases look the same, different things are happening. char *p = "breadfruit";
A string literal created by a pointer initialization is defined as read-only in ANSI C; the program will exhibit undefined behavior if it tries to change the literal by writing through p. Some implementations put string literals in the text segment, where they will be protected with read-only permission. An array can also be initialized with a string literal:
char a[] = "gooseberry"; In contrast to a pointer, an array initialized by a literal string is writable. The individual characters can later be changed. The following statement: strncpy(a, "black", 5); gives the string in the array the new value "blackberry". |