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

Discussion in 'C Programming' started by Trevor, Apr 3, 2004.

  1. Trevor

    Trevor Guest

    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 */
    }
     
    Trevor, Apr 3, 2004
    #1
    1. Advertising

  2. "Trevor" <> 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
     
    Régis Troadec, Apr 3, 2004
    #2
    1. Advertising

  3. Mistake,

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


    if (buf != NULL)
    {

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


    }

    > }
    > /*...*/
     
    Régis Troadec, Apr 3, 2004
    #3
  4. Trevor

    Joe Wright Guest

    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 mailto:
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Apr 3, 2004
    #4
  5. On Fri, 02 Apr 2004 23:28:30 GMT, "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?


    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>>
     
    Barry Schwarz, Apr 3, 2004
    #5
  6. In article <yGmbc.62053$K91.150753@attbi_s02>,
    "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?


    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';
     
    Christian Bau, Apr 3, 2004
    #6
  7. In article <c4l1ea$568$>,
    "Régis Troadec" <> wrote:

    > "Trevor" <> 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...
     
    Christian Bau, Apr 3, 2004
    #7
  8. "Christian Bau" <> a écrit dans le message
    de news:...

    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
     
    Régis Troadec, Apr 4, 2004
    #8
  9. In 'comp.lang.c', Christian Bau <>
    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- [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/
     
    Emmanuel Delahaye, Apr 10, 2004
    #9
  10. Trevor

    CBFalconer Guest

    Emmanuel Delahaye wrote:
    > Christian Bau <> 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 mailto:
    */

    #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 () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
     
    CBFalconer, Apr 10, 2004
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David
    Replies:
    2
    Views:
    484
    Thomas G. Marshall
    Aug 3, 2003
  2. Sullivan WxPyQtKinter

    It is fun.the result of str.lower(str())

    Sullivan WxPyQtKinter, Mar 7, 2006, in forum: Python
    Replies:
    5
    Views:
    344
    Tim Roberts
    Mar 9, 2006
  3. Stefan Ram

    str.equals(null) or str==null ?

    Stefan Ram, Jul 31, 2006, in forum: Java
    Replies:
    21
    Views:
    14,747
    Oliver Wong
    Aug 3, 2006
  4. maestro
    Replies:
    1
    Views:
    312
    Chris
    Aug 11, 2008
  5. newbie30

    *str++ and (*str)++

    newbie30, Aug 12, 2009, in forum: C Programming
    Replies:
    0
    Views:
    782
    newbie30
    Aug 12, 2009
Loading...

Share This Page