home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / lang / c / 12259 < prev    next >
Encoding:
Text File  |  1992-08-12  |  6.7 KB  |  185 lines

  1. Path: sparky!uunet!cs.utexas.edu!hellgate.utah.edu!dog.ee.lbl.gov!horse.ee.lbl.gov!torek
  2. From: torek@horse.ee.lbl.gov (Chris Torek)
  3. Newsgroups: comp.lang.c
  4. Subject: char *foo[] (was Computer terms, etc)
  5. Date: 13 Aug 1992 04:58:38 GMT
  6. Organization: Lawrence Berkeley Laboratory, Berkeley
  7. Lines: 172
  8. Message-ID: <25451@dog.ee.lbl.gov>
  9. References: <cee1.713424953@Isis.MsState.Edu> <19479@fritz.filenet.com> <20900024@inmet>
  10. Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
  11. NNTP-Posting-Host: 128.3.112.15
  12.  
  13. In article <cee1.713424953@Isis.MsState.Edu> cee1@ra.msstate.edu
  14. (Charles Evans) asks for definitions of a bunch of IBM PC specific
  15. terms (which should generally be kept to other newsgroups) and for
  16. explanations about:
  17.  
  18.     *foo[]
  19.     **foo
  20.  
  21. and
  22.  
  23. >char *foo = "abc";
  24. >char *foo[] = "abc";
  25. >char foo[] = "abc";
  26. >char foo[4] = "abc";  <--- is the '\0' automatcially added?
  27.  
  28. So far I have seen three answers, two containing errors and one short
  29. but correct.  (I am not going to quote the correct one here.)
  30.  
  31. In article <19479@fritz.filenet.com> scotth@felix.filenet.com (Scott Hopson)
  32. >*foo[] is a pointer to an array
  33. >**foo is a pointer to a pointer
  34.  
  35. The latter is correct; the former is not.  Given a declaration of the
  36. form
  37.  
  38.     T *x[];
  39.  
  40. (where T is some type), x will probably have this type:
  41.  
  42.     declare x as array UNKNOWN_SIZE of pointer to T
  43.  
  44. But if this is a format parameter declaration---we are obviously missing
  45. some context, so we do not know whether this is the case---then x will
  46. have this type instead:
  47.  
  48.     declare x as pointer to pointer to T
  49.  
  50. The reason is, as usual, an outgrowth of The Rule about arrays in C.
  51. This Rule states that:
  52.  
  53.     Whenever an object of type `array N of T' appears in a value
  54.     context, it is converted to a value of type `pointer to T',
  55.     pointing to the first element of that array, i.e., the one with
  56.     subscript 0.  (N must be some integer constant or the special
  57.     `unknown size' marker, and T must be some valid type.)
  58.  
  59. So if we write:
  60.  
  61.     extern int i[];
  62.  
  63.     void f(a) char a[]; { ... }
  64.  
  65. then `i' is declared as an `array UNKNOWN_SIZE of int', but `a' is not
  66. an array at all.  All actual function arguments are, by definition,
  67. *values*, not objects---if you try, in C, to pass an object to a
  68. function, you simply pass the value of that object.  But a formal
  69. parameter declaration, such as that for `a' here, declares an object,
  70. not a value.
  71.  
  72. Well, obviously there is a conflict here: we claim `a' is an object of
  73. type `array UNKNOWN_SIZE of char', but it must come directly from some
  74. value, and The Rule guarantees that there are no array values.  Dennis
  75. Ritchie decided that the answer to this dilemma was to adjust the type
  76. of `a', silently, in the compiler.  The compiler *knows* `a' cannot be
  77. an array, so it changes `array N of T' to `pointer to T' and then carries
  78. on as if you had written that in the first place.
  79.  
  80. Thus, the compiler adjusts the type, changing `array UNKNOWN_SIZE of char'
  81. to `pointer to char', and this is *exactly the same* as if we wrote
  82. instead:
  83.  
  84.     void f(a) char *a; { ... }
  85.  
  86. Thus, there are places (formal parameter declarations) where `T *foo[]'
  87. and `T **foo' are identical in meaning.  I advise against using the
  88. array notation in these cases.  It generally adds more confusion than
  89. clarity.  Note that formal parameters are the ONLY place where these
  90. are equivalent: at all other times, confusing `array N of T' with
  91. `pointer to T' will get you in trouble.
  92.  
  93. In article <20900024@inmet> richw@inmet.camb.inmet.com writes:
  94. >>  char *foo = "abc";
  95. >>  char *foo[] = "abc";
  96. >>  char foo[] = "abc";
  97. >>  char foo[4] = "abc";
  98.  
  99. >First, let me give these "foo"s unique names:
  100.  
  101. (this is a good idea)
  102.  
  103. >    char *fooA = "abc";
  104. >    char *fooB[] = "abc";
  105. >    char fooC[] = "abc";
  106. >    char fooD[4] = "abc";
  107. >
  108. >Here's a way of rewriting these which might make things clearer:
  109. >
  110. >    static char literal [] = { 'a', 'b', 'c', '\0' };
  111. >
  112. >    /*  "literal" is now a constant which equals the address  */
  113. >    /*  of the first element of an initialized, 4-element     */
  114. >    /*  "char" array                          */
  115. >
  116. >    char *fooA = literal;
  117. >    char *fooB[] = (char **) literal;
  118. >    #define fooC literal
  119. >    #define fooD literal
  120. >
  121. >Thus, "fooC" and "fooD" are identical; both are constants which equal the
  122. >address of the "literal" array's first element.
  123.  
  124. This is mostly right.  The initialization for fooB[], however, is
  125. illegal (as it was in the original example).  If the original version
  126. is repaired (by adding {} around "abc"), one correct translation is:
  127.  
  128.     char *fooB[] = { &literal[0] };
  129.  
  130. In addition, it is somewhat misleading to use the same `literal' for
  131. all four, but it is just as misleading to use a different one for each:
  132. The C language does not say which, if any, identical string contants
  133. live at the same address and which do not.  (It also obscures details
  134. as to whether string constants are read-only; this again is up to the
  135. compiler.)  That is, given:
  136.  
  137.     char *p1 = "abc", *p2 = "abc";
  138.  
  139. the C language leaves unspecified whether p1==p2 or p1!=p2.  Either
  140. is acceptable.  If p1==p2, and if string constants are writable, then
  141. changing *p1 will also change *p2.  If string constants are read-only,
  142. the possibility of p1==p2 is less important.
  143.  
  144. >Note that the "4" in the "char fooD[4]" declaration is entirely unnecessary;
  145. >what's interesting are these cases:
  146. >
  147. >    fooD[3] = "abc";    /*  Illegal !  "fooD" is too small  */
  148. >
  149. >    fooD[5] = "abc";    /*  "fooD" is the constant address  */
  150. >                /*  of the first element of a 5-    */
  151. >                /*  element "char" array whose 5-th */
  152. >                /*  element is uninitialized        */
  153.  
  154. (I assume the word `char' is supposed to appear in front of each of these.)
  155. In ANSI C,
  156.  
  157.     char s[3] = "abc";
  158.  
  159. is explicitly legal, and it makes s[] contain the three characters
  160. 'a', 'b', 'c', omitting the final '\0'.  In Classic C it is illegal.
  161. In both Classic and New C, when
  162.  
  163.     char s[5] = "abc";
  164.  
  165. is legal, it makes s contain the five characters 'a', 'b', 'c', '\0',
  166. '\0'.  (The initialization is legal in Classic C only if `s' has static
  167. duration, while in ANSI C it is always legal.)  That is, the fifth
  168. element of s (or fooD), s[4] (or fooD[4]), *is* initialized, to '\0'.
  169.  
  170. Note that this is *not* what you get if you use strcpy().  Strcpy()
  171. and explicit initialization are different.
  172.  
  173. >Finally, note that "char *fooB[]" represents a pointer to an array, where
  174. >each element of the array is itself a pointer to "char".  This is a
  175. >*different* type than the type of "abc", i.e. a pointer to "char".  I'm
  176. >surprised my C compiler accepted for "fooB" declaration.  In any case,
  177. >I would never write such a declaration...
  178.  
  179. Nearly right: fooB is not a pointer to an array; it is an object of
  180. type `array 1 of pointer to char'.  The initialization is indeed
  181. illegal, and a compiler that silently accepts it is non-conformant.
  182. -- 
  183. In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
  184. Berkeley, CA        Domain:    torek@ee.lbl.gov
  185.