Thread: strncpy question, size -1??

  1. #1
    Registered User
    Join Date
    Jan 2005
    Posts
    15

    strncpy question, size -1??

    hiya guys,

    saw this code, curious as to why the author -1 from the sizeof?

    Code:
    char host[512]
    
    memset (&host, 0, sizeof(host));
    
    strncpy (host, argv[optind], sizeof (host) -1 );
    why wouldnt the strncpy just be the size of host??
    Cheers!

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    The last character wouldn't be copied.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > memset (&host, 0, sizeof(host));
    Unnecessary & here

    > why wouldnt the strncpy just be the size of host?
    Well having expensively filled the array with zeros, by only copying n-1 characters you ensure there is at least one \0 in the string.
    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
    Registered User
    Join Date
    Jan 2005
    Posts
    15
    So do you think the memset is unnesessary here?

    I quite new to mem operations, i assumed it was good to sanatise the array??

    So by coping one less you make sure there is one 0 at the end. Is that was \0 is?

    Sorry, i understand that \0 represents the end of a string, (not sure if that the best way to put it) just didnt know how that is actually represnted. Is a 0 byte = \0 then. Im sure this probably seems very stupid! Just one of those things, self taught so im sure I always miss things I should have leant!

    Thankyou! Appreciate that, clears it up. I thought it was due to some kind of security, stop buffer overflows or something!

    *edit-spelling.

  5. #5
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    The memset is unecessary because it fills the entire buffer with zeroes. However, you need something to ensure there a '\0' (null character) at the end because strncpy is brain damaged. If the source is longer than the destination buffer (according to your specified size) then strncpy won't terminate the string with a null, so you need something to add a null at the end always.

    strncpy's other brain damaged behaviour is to fill the rest of the buffer with nulls if the source is shorter than the destination buffer.

  6. #6
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Quote Originally Posted by cwr
    strncpy's other brain damaged behaviour is to fill the rest of the buffer with nulls if the source is shorter than the destination buffer.
    Not in my compiler.
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int  main()
    {
        char a[] = "abcdefghijklmnop";
        char b[] = "1234567890";
    
        printf("%s \n", a);
        strncpy(a, b, 7);
        printf("%s \n", a);
        
        return 0;
    }
    Output:
    abcdefghijklmnop
    1234567hijklmnop
    Although further testing shows (this is probably what you meant):

    If the source buffer is smaller than the number of characters specified, behaviour of strncpy() is to fill the extra characters in the destination buffer with '\0' until the number of characters specified is reached. IOW,
    Code:
        char a[] = "abcdefghijklmnop";
        char b[] = "123";
        strncpy(a, b, 7);
    7 characters in destination are filled, with '1', '2', '3' and 4 nulls. I don't consider this brain damaged. You asked to move 7 characters. Only 3 were available. Fill the rest with \0. After all, we did specify 7...
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    strncpy's other (other) brain damage is that it doesn't always append a \0.

    > So do you think the memset is unnesessary here?
    Well this does the same thing
    strncpy (host, argv[optind], sizeof (host) -1 );
    host[sizeof (host)-1] = '\0';


    ISTR a website from one of the authors of C explaining the behaviour of strncpy etc. It is a relic of some very old UNIX API as I recall.
    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.

  8. #8
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Quote Originally Posted by Salem
    strncpy's other (other) brain damage is that it doesn't always append a \0.
    I already stated that in my post above.


    Quote Originally Posted by WaltP
    Although further testing shows (this is probably what you meant):

    If the source buffer is smaller than the number of characters specified
    Yes, that's what I meant. I realise my wording was unclear, but obviously the length of the destination buffer has no effect on the behaviour of strncpy, only the specified size, since strncpy doesn't know the length of the destination buffer.

    Quote Originally Posted by WaltP
    7 characters in destination are filled, with '1', '2', '3' and 4 nulls. I don't consider this brain damaged. You asked to move 7 characters. Only 3 were available. Fill the rest with \0. After all, we did specify 7...
    I should say its use is frequently brain damaged from a performance perspective.
    Code:
    char x[16384];
    strncpy(x, src, sizeof x - 1);
    This always writes 16383 characters no matter how long src is. character arrays rarely benefit from being zeroed out as long as we are careful that they have one null character to determine the end.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    15
    Wow, some really interesting responses. Really understand whats going on now.

    Its really interesting how different people approach a subject. Salem, cheers for that sample code, that makes much more sense.

  10. #10
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    How is strncpy not copying a null over a brain damage thing? What if you are only copying part of a string into the middle of another string? Would you really want it putting a null character there?

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    15
    I tried doing what Saleam suggested:

    strncpy (host, argv[optind], sizeof (host) -1 );
    host[sizeof (host)-1] = '\0';

    However the compiler wouldnt let me. Replacing the ='\0'; with = 0; does work thought. Are they the same thing??

  12. #12
    Registered Luser cwr's Avatar
    Join Date
    Jul 2005
    Location
    Sydney, Australia
    Posts
    869
    Quote Originally Posted by Thantos
    How is strncpy not copying a null over a brain damage thing? What if you are only copying part of a string into the middle of another string? Would you really want it putting a null character there?
    If you were deliberately avoiding null termination by copying part of the string, you could just use memcpy instead.

    It's brain damaged because you'd expect a function concerned with copying strings to always result in a string. If you consider that in C, "string" is synonymous with "null terminated character array", and strncpy violates this idea.

    A lot of bad code simply has strncpy(dst, src, sizeof dst); and doesn't bother to explicitly null terminate the string. One might be tempted to say "that's the programmer's fault", and it is, but it also goes against what one expects.

    edit: The C FAQ entry has more info on why strncpy was designed as it was, and also suggests memcpy and/or strncat for accomplishing similar.

  13. #13
    Been here, done that.
    Join Date
    May 2003
    Posts
    1,164
    Quote Originally Posted by cwr
    If you were deliberately avoiding null termination by copying part of the string, you could just use memcpy instead.
    Because strncpy() is the approved string copy function.

    Quote Originally Posted by cwr
    It's brain damaged because you'd expect a function concerned with copying strings to always result in a string. If you consider that in C, "string" is synonymous with "null terminated character array", and strncpy violates this idea.
    No you wouldn't. If you want it null terminated, use strcpy() or strcat().
    strncpy() is meant to move substrings into other strings, not concatinate the source string into the middle of another string erasing the end.

    Quote Originally Posted by cwr
    A lot of bad code simply has strncpy(dst, src, sizeof dst); and doesn't bother to explicitly null terminate the string. One might be tempted to say "that's the programmer's fault", and it is, but it also goes against what one expects.
    They are either using strncpy() wrong, or correctly replacing a substring. One would not expect strncpy() to truncate the string -- by its definition/description.
    Definition: Politics -- Latin, from
    poly meaning many and
    tics meaning blood sucking parasites
    -- Tom Smothers

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > I already stated that in my post above.
    So you did - my mistake.
    And thanks for the link - I'd obviously forgotten that it was in the clc FAQ.

    > However the compiler wouldnt let me
    Explain with an error message - how didn't it "let you" do that?
    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.

  15. #15
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Old New Thing: strncpy

    In short, it would be a good idea to forget that strncpy exists.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  2. Error with a vector
    By Tropicalia in forum C++ Programming
    Replies: 20
    Last Post: 09-28-2006, 07:45 PM
  3. char array size question, please help!
    By Ash1981 in forum C Programming
    Replies: 4
    Last Post: 01-29-2006, 02:30 AM
  4. another exercise question
    By luigi40 in forum C# Programming
    Replies: 3
    Last Post: 11-28-2005, 03:52 PM
  5. Replies: 2
    Last Post: 11-24-2005, 01:30 AM