billf@hpcvlx.cv.hp.com (Bill F. Faus) (03/23/90)
Question: Can someone help me understand why this initialization is legal: char a[] = "hunky dory"; char * p = a; char b = 'x'; char * q = &b; And this isn't: char * q = "wishy washy"; char * p = q; This question has come up as I want to initalize 120K of string data and use the STRS option of Think C so I don't have to worry about data segments. As in: char * bit_map_A = "\012\013\014...."; char * bit_map_B = "\230\231\232...."; ......... char * bit_map_ZZ = "\001\002\003...."; If instead I had used char arrays instead of char pointers: char * bit_map_A[] = "\012\013\014...."; Then I could subsequently intialize an array of bitmaps like: char * bit_map_ptr[] = {bit_map_A, bit_map_B, ...., bit_map_ZZ}; The 'bind' I get in is that arrays intialized with string literals get allocated in the main data segment, so I run out of room but I CAN use the nifty feature of referring to the array name in subsequent initialization statments. Whereas pointers initialized to string literals get allocated to the automatic STRS data segments but I CANNOT refer to the pointer names in subsequent initialization statements. --------------- billf@cv.hp.com
wilson@ernie.Berkeley.EDU (James E. Wilson) (03/26/90)
In article <101780005@hpcvlx.cv.hp.com> billf@hpcvlx.cv.hp.com (Bill F. Faus) writes: > Can someone help me understand why this initialization is legal: > char a[] = "hunky dory"; > char * p = a; > > char b = 'x'; > char * q = &b; > > And this isn't: > char * q = "wishy washy"; > char * p = q; Although pointers and arrays are generally equivalent, there are some very important differences between them. In short, when specifying an initial value for a global or static variable, the value must be a constant known at compile time. This is true for 'a' which is an array and for '&b' which is the address of a variable, but is not true for 'q' which is a pointer. A longer explanation follows. First of all, since 'a' is declared as an array, space is allocated for its contents. However, no space is allocated for 'a' itself. The value of 'a' is the address where the array contents are stored, and this value is a compile-time constant. If you think of 'a' as a constant, then this explains why arrays behave as they do. For example, "a = q;" is illegal because you can't modify the value of constants. "char *p = a;" is legal because 'a' is a constant known at compile time. Also, this explains why "p = &a;" makes no sense. You can not take the address of an array 'a', because it is a constant, and hence does not have an address. You should think of "p = &a;" as equivalent to "p = &1000;" which also make no sense. What happens when you write this depends on what compiler you are using. Some compilers treat this the same as "p = a"; some compilers say "Warning: ampersand before array ignored" and treat it the same as "p = a"; and finally, some compilers consider this an error and will refuse to compile it. It is best to write "p = a" assuming that that is what you meant. If you really wanted a doubly indirect pointer to the array, then declare a variable to hold the address of the array, and then take the address of the new variable. Secondly, "char *q = &b;" is legal because 'b' is a variable (of type char), and its address is a constant known at compile time. Thirdly, "char *p = q;" is not legal because 'q' is a char pointer, and the value of 'q' is NOT a constant. > This question has come up as I want to initalize 120K of string > data and use the STRS option of Think C so I don't have to worry > about data segments. As in: > char * bit_map_A = "\012\013\014...."; > ......... > char * bit_map_ZZ = "\001\002\003...."; > > If instead I had used char arrays instead of char pointers: > char * bit_map_A[] = "\012\013\014...."; > Then I could subsequently intialize an array of bitmaps like: > char * bit_map_ptr[] = {bit_map_A, bit_map_B, ...., bit_map_ZZ}; "char * bit_map_A[] = "\012..." will give a type mismatch error, I assume you mean "char bit_map_A[] = "\012..." The easiest solution would be to define an array of "char **", and put the addresses of your strings in it, i.e. char *bit_map_A = "\012..." ... char *bit_map_ZZ = "\001..." and then char **bit_map_ptr[] = {&bit_map_A, &bit_map_B, ..., &bit_map_ZZ}; Alternatively, you can write a small program which will read in the string values (from a ascii file with scanf() or from a binary data file with fgets()) and then write them into appropriately sized resources, and then save the resources into a file. Then to use them, for example, char **bit_map_A; bit_map_A = GetResource(...); and then bit_map_A[0] is a string. This works best with simple data structures, though. Creating an array of string pointers is tricky. It is much easier to create an array of fixed sized strings as a resource. Jim Wilson wilson@ernie.Berkeley.EDU "...black men in Harlem (a part of New York City) were less likely to reach the age of 65 than men in Bangladesh (one of the worlds poorest nations)..." -- New England Journal of Medicine, January 1990