home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / c / 18818 < prev    next >
Encoding:
Text File  |  1992-12-23  |  2.9 KB  |  87 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!uunet.ca!wildcan!sq!msb
  3. From: msb@sq.sq.com (Mark Brader)
  4. Subject: Re: definition of strncpy stupid?
  5. Message-ID: <1992Dec23.100054.2939@sq.sq.com>
  6. Summary: No, don't use sprintf() after all.
  7. Organization: SoftQuad Inc., Toronto, Canada
  8. References: <1992Dec8.181543.15339@dnbf01.bram.cdx.mot.com> <1992Dec9.144743.1863@rti.rti.org> <16298@goanna.cs.rmit.oz.au>
  9. Date: Wed, 23 Dec 92 10:00:54 GMT
  10. Lines: 75
  11.  
  12. > I realise this thread has been running for a while, but I think I have
  13. > something new to say.
  14.  
  15. Me too!
  16.  
  17. I too advocated the use of sprintf() with a "%.*s" format directive
  18. as a replacement for strncpy() which writes exactly one null.  And I
  19. still stand by this recommendation for most purposes, but there is
  20. an important caveat which I forgot, and have not seen mentioned here.
  21.  
  22. Which is: an implementation is allowed to limit the length of the
  23. string converted by a single format directive in any of the printf()
  24. family functions.  In ANSI C, the limit may be as short as 509 bytes.
  25. Now in most cases when you use strncpy(), you know what the length
  26. argument is, and it *is* a number smaller than 509.  But if this is
  27. not the case, then do *not* use sprintf() to replace strncpy().
  28.  
  29. Unfortunately, if you do have to deal with very long strings (in which
  30. case efficiency is more likely to matter), there isn't really any way
  31. of doing a length-limited copy that's known to be efficient and to work.
  32.  
  33. If you say
  34.     strncpy (dest, src, n-1);
  35.     dest[n-1] = '\0';
  36. then strncpy() has to write a lot of nulls if the string is short.
  37.  
  38. If you say
  39.     memcpy (dest, src, n-1);
  40.     dest[n-1] = '\0';
  41. then you risk a memory access error if the source string comes from
  42. an array shorter than n-1 bytes, and you're copying unnecessary bytes
  43. if the string is short.
  44.  
  45. If you say
  46.     if (strlen (src) >= n) {
  47.         memcpy (dest, src, n-1);
  48.         dest[n-1] = '\0';
  49.     } else
  50.         strcpy (dest, src);
  51. then you are taking an extra pass through the source string, which is
  52. inefficient if it is long.
  53.  
  54. If you say
  55.     int tmp;
  56.     tmp = src[n-1];
  57.     src[n-1] = '\0';
  58.     strcpy (dest, src);
  59.     src[n-1] = tmp;
  60. then you risk a memory access error if the source string is not writable,
  61. or if it comes from an array shorter than n bytes.
  62.  
  63. If you say
  64.     sprintf (dest, "%.*s", n, src);
  65. then you run into the limitation noted above.
  66.  
  67. And if you say
  68.     int i;
  69.     for (i = 0; i < n && src[i]; ++i)
  70.         dest[i] = src[i];
  71.     if (i == n)
  72.         dest[--i] = '\0';
  73. , or the equivalent with advancing pointers, then you risk the code
  74. being significantly slower than an efficient library implementation of
  75. one of the other methods.
  76.  
  77. Sigh.
  78.  
  79. NOTE: none of the code fragments in this article have been tested.
  80. Use at your own risk.
  81. -- 
  82. Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
  83.     "I'm a little worried about the bug-eater," she said.  "We're embedded
  84.     in bugs, have you noticed?"        -- Niven, "The Integral Trees"
  85.  
  86. This article is in the public domain.
  87.