home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c
- Path: sparky!uunet!uunet.ca!wildcan!sq!msb
- From: msb@sq.sq.com (Mark Brader)
- Subject: Re: definition of strncpy stupid?
- Message-ID: <1992Dec23.100054.2939@sq.sq.com>
- Summary: No, don't use sprintf() after all.
- Organization: SoftQuad Inc., Toronto, Canada
- References: <1992Dec8.181543.15339@dnbf01.bram.cdx.mot.com> <1992Dec9.144743.1863@rti.rti.org> <16298@goanna.cs.rmit.oz.au>
- Date: Wed, 23 Dec 92 10:00:54 GMT
- Lines: 75
-
- > I realise this thread has been running for a while, but I think I have
- > something new to say.
-
- Me too!
-
- I too advocated the use of sprintf() with a "%.*s" format directive
- as a replacement for strncpy() which writes exactly one null. And I
- still stand by this recommendation for most purposes, but there is
- an important caveat which I forgot, and have not seen mentioned here.
-
- Which is: an implementation is allowed to limit the length of the
- string converted by a single format directive in any of the printf()
- family functions. In ANSI C, the limit may be as short as 509 bytes.
- Now in most cases when you use strncpy(), you know what the length
- argument is, and it *is* a number smaller than 509. But if this is
- not the case, then do *not* use sprintf() to replace strncpy().
-
- Unfortunately, if you do have to deal with very long strings (in which
- case efficiency is more likely to matter), there isn't really any way
- of doing a length-limited copy that's known to be efficient and to work.
-
- If you say
- strncpy (dest, src, n-1);
- dest[n-1] = '\0';
- then strncpy() has to write a lot of nulls if the string is short.
-
- If you say
- memcpy (dest, src, n-1);
- dest[n-1] = '\0';
- then you risk a memory access error if the source string comes from
- an array shorter than n-1 bytes, and you're copying unnecessary bytes
- if the string is short.
-
- If you say
- if (strlen (src) >= n) {
- memcpy (dest, src, n-1);
- dest[n-1] = '\0';
- } else
- strcpy (dest, src);
- then you are taking an extra pass through the source string, which is
- inefficient if it is long.
-
- If you say
- int tmp;
- tmp = src[n-1];
- src[n-1] = '\0';
- strcpy (dest, src);
- src[n-1] = tmp;
- then you risk a memory access error if the source string is not writable,
- or if it comes from an array shorter than n bytes.
-
- If you say
- sprintf (dest, "%.*s", n, src);
- then you run into the limitation noted above.
-
- And if you say
- int i;
- for (i = 0; i < n && src[i]; ++i)
- dest[i] = src[i];
- if (i == n)
- dest[--i] = '\0';
- , or the equivalent with advancing pointers, then you risk the code
- being significantly slower than an efficient library implementation of
- one of the other methods.
-
- Sigh.
-
- NOTE: none of the code fragments in this article have been tested.
- Use at your own risk.
- --
- Mark Brader, SoftQuad Inc., Toronto, utzoo!sq!msb, msb@sq.com
- "I'm a little worried about the bug-eater," she said. "We're embedded
- in bugs, have you noticed?" -- Niven, "The Integral Trees"
-
- This article is in the public domain.
-