home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / lang / c / 17075 < prev    next >
Encoding:
Text File  |  1992-11-24  |  5.7 KB  |  144 lines

  1. Path: sparky!uunet!zaphod.mps.ohio-state.edu!cs.utexas.edu!sun-barr!ames!agate!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: Re: Where are literals stored?
  5. Date: 24 Nov 1992 01:34:12 GMT
  6. Organization: Lawrence Berkeley Laboratory, Berkeley
  7. Lines: 131
  8. Message-ID: <27627@dog.ee.lbl.gov>
  9. References: <27542@dog.ee.lbl.gov> <By0vzy.4Ly@ocsmd.ocs.com> <14542.610.uupcb@spacebbs.com> <27583@dog.ee.lbl.gov>
  10. Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
  11. NNTP-Posting-Host: 128.3.112.15
  12.  
  13. In article <27542@dog.ee.lbl.gov> I claimed that strings used as array
  14. initializers are not `string literals'.  Mark Brader and others inform
  15. me that my terminology disagreed with the standard, so I will abandon
  16. that.  (I just moved and my copy of the standard is in a box somewhere
  17. within a pile of furniture....  On the bright side, I now live two
  18. blocks from campus, and hence from the free LBL shuttle.)
  19.  
  20. In article <14542.610.uupcb@spacebbs.com> ted.jensen@spacebbs.com
  21. (Ted Jensen) writes:
  22. >... according to K&R2 p194 under "A2.6 String Literals"
  23. >"A string literal, also called a string constant, is a sequence
  24. >of characters surrounded by double quotes, as in "..."."
  25. >"A string has type 'array of characters' and storage class static
  26. >and is initialized with the given characters."
  27.  
  28. Note that K&R-2 is not the standard, and is itself sometimes at
  29. variance with the standard.  (Neither of the quoted statements are
  30. wrong in and of themselves, as far as I know, but they do not tell
  31. the whole story.)
  32.  
  33. >void my_func(void) {
  34. >  static char a[] = "ABC";
  35. >  char b[] = "ABC";
  36.  
  37. >The actual strings themselves were, in both cases, stored in the
  38. >data segment. ...
  39.  
  40. I will note (without reference to the standard, although I am confident
  41. that this is correct) that a compiler will have to emit `a' in a data
  42. segment (or local system quivalent).  On the other hand, `b' could be
  43. set up with something like:
  44.  
  45.     // hypothetical 16-bit big-endian machine
  46.     sub    #4,sp        // make room for 4 bytes
  47.     mov    #'AB',0(sp)    // set b[0], b[1]
  48.     mov    #'C\0',2(sp)    // set b[2], b[3]
  49.  
  50. This might take less space and time than a call to strcpy() or memcpy(),
  51. and would violate nothing in the standard, but it would mean that the
  52. "ABC\0" for array `b' would appear nowhere in the source code.
  53.  
  54. >In the case of array b[] the [Borland] code, on entering the function at
  55. >run time, copies the string from the data segment to the stack and 'b'
  56. >takes on the value of a pointer pointing to the string now on the stack.
  57. >This was not clear from some of the replies which, IMHO, made it sound
  58. >like that in the case of b[] the string literal ABC was not stored in
  59. >the data segment.
  60.  
  61. There is no reason that the string "ABC" *must* appear in the data
  62. segment (other than for a[]); the Borland compiler merely uses this
  63. as an implementation technique.
  64.  
  65. In article <27583@dog.ee.lbl.gov> I noted that
  66. >... It is not completely clear whether merging overlapping literals
  67. >is permitted by the ANSI standard, but I would not object to a compiler
  68. >that did so.
  69.  
  70. Several people have sent mail asking how a conformant program could
  71. tell whether a compiler has done so.  (If a conformant program cannot
  72. test for some effect, that effect is implicitly allowed under the
  73. `as-if' rule.)
  74.  
  75. The standard leaves undefined the effect of `<' or `>' comparsions on
  76. pointers to different objects, but the `==' and `!=' comparisons are
  77. fully specified.  In particular, given any two valid pointers `p' and
  78. `q', of the same type, the standard tells us that:
  79.  
  80.     p == q     if and only if they point to the same object;
  81.     p != q     otherwise.
  82.  
  83. (This rule can have negative effects on run time for segmented
  84. implementations.  In particular, on some PCs, == and != comparisons of
  85. pointers must normalize the pointers, while </> comparisons can compare
  86. only the offsets.  This means that, in some cases, a loop of the form:
  87.  
  88.     for (p = &a[0]; p < &a[N]; p++)
  89.  
  90. will run faster than one of the form:
  91.  
  92.     for (p = &a[0]; p != &a[N]; p++)
  93.  
  94. A compiler needs to perform some analysis to discover that these are
  95. equivalent [assuming they are in fact equivalent; this depends on the
  96. loop body]).
  97.  
  98. Anyway, given this fact, we can write:
  99.  
  100.     (p + strlen(p)) == (q + strlen(q))
  101.  
  102. to see whether or not two strings overlap.  This compares pointers to
  103. the objects (of type char or const char) holding the '\0's that end
  104. those strings.  Those pointers will be equal if and only if the two
  105. objects are in fact the same single object.  (Thanks to someone whose
  106. mail address I failed to save for this simplification---I was going
  107. to run a pointer forward along the longer string to look for overlap!)
  108.  
  109. So, we can now write a strictly conformant program along these lines:
  110.  
  111.     #include <stdio.h>
  112.     #include <stdlib.h>
  113.  
  114.     int main(void) {
  115.         char *p, *q;
  116.  
  117.         p = "string";
  118.         q = "ring";
  119.         if (p + strlen(p) == q + strlen(q))
  120.             printf("this compiler merged (%s,%s)\n", p, q);
  121.         else
  122.             printf("this compiler did not merge (%s,%s)\n", p, q);
  123.         exit(EXIT_SUCCESS);
  124.     }
  125.  
  126. The standard does not explicitly grant license to compilers to do such
  127. merging unless the strings exactly match (e.g., "string" and
  128. "string").  On the other hand, the standard does not explicitly
  129. prohibit this either.  It *does* say that pointers to distinct objects
  130. always compare unequal, and "string" and "ring" are certainly distinct
  131. objects---but are the last four characters of each *also* distinct
  132. objects?  This is where comp.std.c gets involved. :-)
  133.  
  134. Note that if we write, e.g.,
  135.  
  136.     char ap[] = "string", aq[] = "ring";
  137.  
  138. we can tell from the standard that ap + strlen(ap) != aq + strlen(aq).
  139. Pointers to anonymous `string objects' are quite different from pointers
  140. into named arrays.
  141. -- 
  142. In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
  143. Berkeley, CA        Domain:    torek@ee.lbl.gov
  144.