Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > sizeof(str) or sizeof(str) - 1 ?

Reply
Thread Tools

sizeof(str) or sizeof(str) - 1 ?

 
 
Trevor
Guest
Posts: n/a
 
      04-02-2004
If I have a string that should be NULL terminated, is it good practice to
use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?
If I have a 'string' that should NOT be NULL terminated, is it good practice
to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
strncpy?

Is this function bug-free?

void setname(char *name)
{
char null_buf[256];
char buf[256];
strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */
}


 
Reply With Quote
 
 
 
 
Régis Troadec
Guest
Posts: n/a
 
      04-03-2004

"Trevor" <(E-Mail Removed)> a écrit dans le message de
news:yGmbc.62053$K91.150753@attbi_s02...

Hi,

> If I have a string that should be NULL terminated, is it good practice to
> use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?
> If I have a 'string' that should NOT be NULL terminated, is it good

practice
> to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
> strncpy?


When using strncpy, you deal with strings, perhaps much more accessed
through pointers than using arrays. In this case, sizeof isn't really
appropriate.
Why don't you use strlen instead of the sizeof operator ?

> Is this function bug-free?


No, It probably crashes if name is null.

> void setname(char *name)
> {
> char null_buf[256];
> char buf[256];
> strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
> strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */


Both of these preserve the terminating null character if name is shorter
than 255 characters (including \0) and is zero-terminated.

If you don't wan't to keep the terminating null character, you'll do
someting like this :

void setname(const char * name)
{
char * buf;
/*...*/
if (name!= NULL)
{
buf = malloc(strlen(name));
strncpy(buf, name, strlen(name));
}
/*...*/
}

Regis


 
Reply With Quote
 
 
 
 
Régis Troadec
Guest
Posts: n/a
 
      04-03-2004
Mistake,

> void setname(const char * name)
> {
> char * buf;
> /*...*/
> if (name!= NULL)
> {
> buf = malloc(strlen(name));


if (buf != NULL)
{

> strncpy(buf, name, strlen(name));


}

> }
> /*...*/



 
Reply With Quote
 
Joe Wright
Guest
Posts: n/a
 
      04-03-2004
Trevor wrote:

> If I have a string that should be NULL terminated, is it good practice to
> use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?
> If I have a 'string' that should NOT be NULL terminated, is it good practice
> to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
> strncpy?
>
> Is this function bug-free?
>
> void setname(char *name)
> {
> char null_buf[256];
> char buf[256];
> strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
> strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */
> }
>
>


A 'string' is NUL or '\0' terminated, by definition (not NULL). A
'string' is neither a variable nor a type. You can't apply sizeof to a
'string'. So let's start over with arrays of char.

char buf[256];

...is simply space, a place that can hold 256 variables of type char.

char *name = "Hello";

Now name points to a literal string of exactly six objects of type char.
The six are 'H', 'e', 'l', 'l', 'o', '\0'.

strncpy(buf, name, sizeof buf);

This will copy the six chars of name into buf and fill the remaining 250
chars of buf with '\0'.

strncpy(buf, name, sizeof buf - 1);

This will copy the six chars of name into buf and fill 249 of the
remaining 250 chars of buf with '\0'. Hmm? I'm not clear on your
'preserve the NUL terminator' question.
--
Joe Wright (E-Mail Removed)
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      04-03-2004
On Fri, 02 Apr 2004 23:28:30 GMT, "Trevor" <(E-Mail Removed)> wrote:

>If I have a string that should be NULL terminated, is it good practice to
>use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?


sizeof is only useful if string is in an array whose definition is in
scope (not one passed in to a function). The answer to your question
is determined by whether or not you want to copy the terminal '\0'.

>If I have a 'string' that should NOT be NULL terminated, is it good practice
>to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
>strncpy?


If it is not '\0' terminated (not NULL which is something else), then
it is not a string by definition. The value that you use for strncpy
is based solely on the number of characters you want to copy.

>
>Is this function bug-free?
>
>void setname(char *name)
>{
> char null_buf[256];
> char buf[256];
> strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
> strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */


Your comments are backwards. They are also misleading. If strncpy
detects a '\0', it will copy it in either case. Neither one will
overrun the destination array so they are bug free in that sense.

>}



<<Remove the del for email>>
 
Reply With Quote
 
Christian Bau
Guest
Posts: n/a
 
      04-03-2004
In article <yGmbc.62053$K91.150753@attbi_s02>,
"Trevor" <(E-Mail Removed)> wrote:

> If I have a string that should be NULL terminated, is it good practice to
> use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?
> If I have a 'string' that should NOT be NULL terminated, is it good practice
> to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
> strncpy?


Just because strncpy is in the Standard C library doesn't mean you
should use it. Its definition makes it basically useless. First, lets
say you were generous and the size of str is 10000 bytes. Every call of
strncpy (str, "Hello", 10000) will copy five characters and then set
9995 bytes to zero. What's worse, you are not guaranteed to end up with
a legitimate string. I suggest writing your own function, like

void my_strncpy (char* dst, const char* src, size_t maxlen)
{
if (strlen (src) < maxlen) {
strcpy (dst, src);
} else if (maxlen > 0) {
memcpy (dst, src, maxlen - 1);
dst [maxlen - 1] = '\0';
}
}



> Is this function bug-free?
>
> void setname(char *name)
> {
> char null_buf[256];
> char buf[256];
> strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
> strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */
> }


If strlen (name) >= 255, then null_buf will contain the first 255
characters of name, followed by an indeterminate character, so it is
highly unlikely to be a legitimate C string.

What you can do:

strncpy (buf, name, sizeof (buf));
buf [sizeof (buf) - 1] = '\0';
or
strncpy (buf, name, sizeof (buf) - 1);
buf [sizeof (buf) - 1] = '\0';
 
Reply With Quote
 
Christian Bau
Guest
Posts: n/a
 
      04-03-2004
In article <c4l1ea$568$(E-Mail Removed)>,
"Régis Troadec" <(E-Mail Removed)> wrote:

> "Trevor" <(E-Mail Removed)> a écrit dans le message de
> news:yGmbc.62053$K91.150753@attbi_s02...
>
> Hi,
>
> > If I have a string that should be NULL terminated, is it good practice to
> > use "sizeof(str)" or "sizeof(str) - 1" when using a function like strncpy?
> > If I have a 'string' that should NOT be NULL terminated, is it good

> practice
> > to use "sizeof(str) - 1" or "sizeof(str)" when using a function like
> > strncpy?

>
> When using strncpy, you deal with strings, perhaps much more accessed
> through pointers than using arrays. In this case, sizeof isn't really
> appropriate.
> Why don't you use strlen instead of the sizeof operator ?


Because it is nonsense? To use strncpy, you must know how much space is
available to hold the result. If 1000 bytes of space are available, then
pass 1000 to strncpy. If I called strcpy (dst, "Hello") first, your idea
would mean that only the first five bytes of dst can be used. Worse yet,
it makes it impossible to copy a string to an uninitialised array.


> > Is this function bug-free?

>
> No, It probably crashes if name is null.
>
> > void setname(char *name)
> > {
> > char null_buf[256];
> > char buf[256];
> > strncpy(buf, name, sizeof(buf)); /* don't preserver NULL terminator */
> > strncpy(null_buf, name, sizeof(buf) - 1); /* preserve NULL terminator */

>
> Both of these preserve the terminating null character if name is shorter
> than 255 characters (including \0) and is zero-terminated.
>
> If you don't wan't to keep the terminating null character, you'll do
> someting like this :
>
> void setname(const char * name)
> {
> char * buf;
> /*...*/
> if (name!= NULL)
> {
> buf = malloc(strlen(name));
> strncpy(buf, name, strlen(name));
> }
> /*...*/
> }


Could you explain to us what that function would be good for? There is
no way for the caller to find out how many characters are stored in buf,
so that is useless. Oh, I noticed you forgot to return buf to the
caller... So you created a memory leak full of garbage data...
 
Reply With Quote
 
Régis Troadec
Guest
Posts: n/a
 
      04-03-2004

"Christian Bau" <(E-Mail Removed)> a écrit dans le message
de news:(E-Mail Removed)...

Hi,

>
> > When using strncpy, you deal with strings, perhaps much more accessed
> > through pointers than using arrays. In this case, sizeof isn't really
> > appropriate.
> > Why don't you use strlen instead of the sizeof operator ?

>
> Because it is nonsense? To use strncpy, you must know how much space is
> available to hold the result. If 1000 bytes of space are available, then
> pass 1000 to strncpy.


It's not a nonsense I think :
- How could you apply sizeof to a pointer ?
- Another common way to use strncpy() is to copy only the N first
characters of the source string in the destination string.

Sure, the main purpose of strncpy() is to provide a safer way to copy
strings than strcpy(), and I think that if you know the available space in
the destination buffer, you should directly pass it to strncpy(). In
strncpy, sizeof should be only applied to arrays whose size isn't known.

> >
> > void setname(const char * name)
> > {
> > char * buf;
> > /*...*/
> > if (name!= NULL)
> > {
> > buf = malloc(strlen(name));
> > strncpy(buf, name, strlen(name));
> > }
> > /*...*/
> > }

>
> Could you explain to us what that function would be good for?


Answering to the OP question about obtaining a not null terminated *string*.

> There is no way for the caller to find out how many characters are stored

in buf,
> so that is useless.


Sure he can: using strlen and adding another function argument.

> Oh, I noticed you forgot to return buf to the
> caller... So you created a memory leak full of garbage data...


But you did'nt notice my /*...*/ lines, which mean that you can have extra
code and other processings in the function, you could'nt guess. buf could
only be a local pointer to serve in many other processings in the function,
and would be of course freed as soon as it's useless.

Regis


 
Reply With Quote
 
Emmanuel Delahaye
Guest
Posts: n/a
 
      04-10-2004
In 'comp.lang.c', Christian Bau <(E-Mail Removed)>
wrote:

> I suggest writing your own function, like
>
> void my_strncpy (char* dst, const char* src, size_t maxlen)
> {
> if (strlen (src) < maxlen) {
> strcpy (dst, src);
> } else if (maxlen > 0) {
> memcpy (dst, src, maxlen - 1);
> dst [maxlen - 1] = '\0';
> }
> }


I think that scanning the string twice (strlen(), strcpy()) is not a good
idea. Here is my STR_safecopy() (from my personal library at
http://mapage.noos.fr/emdel)

char *STR_safecopy (char *const des
,size_t const size
,char const *const src)
{
char *s_out = NULL;
if (des && size && src)
{
memcpy (des, src, size - 1);
des[size - 1] = 0;
s_out = des;
}

return s_out;
}

--
-ed- http://www.velocityreviews.com/forums/(E-Mail Removed) [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      04-10-2004
Emmanuel Delahaye wrote:
> Christian Bau <(E-Mail Removed)> wrote:
>
>> I suggest writing your own function, like
>>
>> void my_strncpy (char* dst, const char* src, size_t maxlen)
>> {
>> if (strlen (src) < maxlen) {
>> strcpy (dst, src);
>> } else if (maxlen > 0) {
>> memcpy (dst, src, maxlen - 1);
>> dst [maxlen - 1] = '\0';
>> }
>> }

>
> I think that scanning the string twice (strlen(), strcpy()) is not
> a good idea. Here is my STR_safecopy() (from my personal library at
> http://mapage.noos.fr/emdel)


You can also use a prototype that has been well tested (see
references) and, in my implementation, does not use the standard
library at all. If the names strlcpy/strlcat create any problems
change them. BSD systems, will not, I believe, need any
implementation whatsoever. This code is deliberately minimized,
for performance reasons.

Please read the reference at:
<http://www.courtesan.com/todd/papers/strlcpy.html>

/* ------- file strlcpy.h ------- */
#ifndef strlcpy_h_
#define strlcpy_h_

#ifdef __cplusplus
extern "C" {
#endif

/* Implementation of strlcpy and strlcat
See http://www.courtesan.com/todd/papers/strlcpy.html

These routines are explicitly designed to move no
data and simply return the projected size of the
final strings when called with sz == 0.

In addition they treat src == NULL as an empty string

strlcat expects that the sz parameter is greater than
the size of the dst string. If not, the treatment is
exactly the same as if a sz value of 0 was used.

NOTE: these routines are deliberately designed to
not require any assistance from the standard
libraries. This makes them more useful in any
embedded systems that must minimize the load size.

Public domain, by C.B. Falconer
bug reports to (E-Mail Removed)
*/

#include <stddef.h>

size_t strlcpy(char *dst, const char *src, size_t sz);
size_t strlcat(char *dst, const char *src, size_t sz);

#ifdef __cplusplus
}
#endif

#endif
/* ------- End file strlcpy.h ------- */

/* ------- file strlcpy.c ------- */
#include "strlcpy.h"

/* ---------------------- */

size_t strlcpy(char *dst, const char *src, size_t sz)
{
const char *start = src;

if (src && sz--) {
while ((*dst++ = *src))
if (sz--) src++;
else {
*(--dst) = '\0';
break;
}
}
if (src) {
while (*src++) continue;
return src - start - 1;
}
else if (sz) *dst = '\0';
return 0;
} /* strlcpy */

/* ---------------------- */

size_t strlcat(char *dst, const char *src, size_t sz)
{
char *start = dst;

while (*dst++) /* assumes sz >= strlen(dst) */
if (sz) sz--; /* i.e. well formed string */
dst--;
return dst - start + strlcpy(dst, src, sz);
} /* strlcat */

/* testing code snipped */
/* ------- End file strlcpy.c ------- */

Some comments and testing have been snipped. The unaltered files
are available at:

<http://cbfalconer.home.att.net/download/strlcpy.zip>

--
Chuck F ((E-Mail Removed)) ((E-Mail Removed))
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments