Thread: Badly designed n string functions?

  1. #1
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544

    Badly designed n string functions?

    Can anyone tell me why the n string functions are seemingly so poorly designed?

    strncpy, wcsncpy.

    These do not guarantee a terminating null if the source string is longer than the destination, and if the destination is longer than the source they will pad with null bytes.

    Who wants this behaviour? The first is dangerous and leads to extra code and the second is totally inefficient. Both are not generally needed.

    For example, if I have a function that takes a string and I want to make a copy to modify I can do this:

    Code:
    char szCopy[512];
    
    if (strlen(szInput) >= 512) return E_INVALIDARG;
    strcpy(szCopy, szInput);
    
    OR:
    
    strncpy(szCopy, szInput, 512);
    if (szCopy[511] != '\0') return E_INVALIDARG;
    So to perform this common simple operation with the std
    functions is quite inefficient.

    I have to turn to the MS string library or write my own function to perform this extremely simple operation efficiently:
    Code:
    if (FAILED(StringCchCopy(szCopy, 512, szInput))) return E_INVALIDARG;
    Am I missing something?

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    True, but all that you need to do to guarantee the NULL is to pass your maxlen-1 as the parameter. But yes, I'll agree with you there. Should've been the default behaviour in the first place.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    I think I saw this on BWK's home page somewhere, but I can't find it at the moment.

    strncpy() was originally designed for certain unix data structures which contained fixed length strings with an optional \0 (eg filenames in inodes).
    Since everyone knew the size of the string, the lack of a \0 was not a particular problem.

    The problems arise when trying to use strncpy() to always guarantee a \0 terminated string, and then people remark on the lack of a guaranteed \0.

    Basically, it's a relic of the past - like gets() - which has little or no use in todays programming environments.

    If you don't care about whether the string is too long, then something like
    Code:
    char *strlcpy ( char *dest, const char *src, size_t len ) {
        strncpy( dest, src, len );
        dest[len-1] = '\0';
        return dest;
    }
    Returns dest, in keeping with the other str functions

    Or perhaps
    Code:
    int strlcpy ( char *dest, const char *src, size_t len ) {
        int res;
        strncpy( dest, src, len );
        res = dest[len-1];
        dest[len-1] = '\0';
        return res;
    }
    This returns 0 if the string fitted in the buffer, or non-zero if the source string was too big.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Thanks for the info.

    I figured they must have been designed for some specific purpose and then leaked into general use.

    The function strlcpy function, if not already, should be in the faq under 'How do I use strncpy?'

    True, but all that you need to do to guarantee the NULL is to pass your maxlen-1 as the parameter.
    This assumes that the string is zeroed out. I use this trick for global strings or when part of a structure that has been zeroed out.

    I could just avoid the mess and use strdup but this incurs the cost of a heap alloc.

    EDIT: I've just noticed that strdup is non-standard. It seems to be pretty wide spread though.
    Last edited by anonytmouse; 11-01-2003 at 06:20 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Replies: 8
    Last Post: 04-25-2008, 02:45 PM
  3. How properly inherit from template?
    By 6tr6tr in forum C++ Programming
    Replies: 118
    Last Post: 04-25-2008, 04:30 AM
  4. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  5. string handling
    By lessrain in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 07:36 PM