C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 03-15-2006, 11:39 AM   #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!
fayte is offline   Reply With Quote
Old 03-15-2006, 11:41 AM   #2
Frequently Quite Prolix
 
dwks's Avatar
 
Join Date: Apr 2005
Location: Canada
Posts: 7,698
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.
dwks is offline   Reply With Quote
Old 03-15-2006, 12:19 PM   #3
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,710
> 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.

Salem is offline   Reply With Quote
Old 03-15-2006, 02:10 PM   #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.
fayte is offline   Reply With Quote
Old 03-15-2006, 06:51 PM   #5
cwr
Registered Luser
 
cwr's Avatar
 
Join Date: Jul 2005
Location: Singapore
Posts: 867
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.
cwr is offline   Reply With Quote
Old 03-16-2006, 12:50 AM   #6
Been here, done that.
 
Join Date: May 2003
Posts: 1,036
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:
Quote:
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...
__________________
There are only 10 types of people in the world -- those that use binary, and those that don't
WaltP is offline   Reply With Quote
Old 03-16-2006, 02:10 AM   #7
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,710
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.

Salem is offline   Reply With Quote
Old 03-16-2006, 03:30 AM   #8
cwr
Registered Luser
 
cwr's Avatar
 
Join Date: Jul 2005
Location: Singapore
Posts: 867
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.
cwr is offline   Reply With Quote
Old 03-16-2006, 06:07 AM   #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.
fayte is offline   Reply With Quote
Old 03-16-2006, 06:35 AM   #10
& the hat of GPL slaying
 
Thantos's Avatar
 
Join Date: Sep 2001
Posts: 5,732
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?
Thantos is offline   Reply With Quote
Old 03-16-2006, 06:55 AM   #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??
fayte is offline   Reply With Quote
Old 03-16-2006, 10:39 AM   #12
cwr
Registered Luser
 
cwr's Avatar
 
Join Date: Jul 2005
Location: Singapore
Posts: 867
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.
cwr is offline   Reply With Quote
Old 03-16-2006, 12:17 PM   #13
Been here, done that.
 
Join Date: May 2003
Posts: 1,036
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.
__________________
There are only 10 types of people in the world -- those that use binary, and those that don't
WaltP is offline   Reply With Quote
Old 03-16-2006, 12:23 PM   #14
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,710
> 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.

Salem is offline   Reply With Quote
Old 03-16-2006, 08:56 PM   #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.
anonytmouse is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
[Tutorial] Implementing the Advanced Encryption Standard KONI C Programming 16 11-23-2007 01:48 PM
Error with a vector Tropicalia C++ Programming 20 09-28-2006 07:45 PM
char array size question, please help! Ash1981 C Programming 4 01-29-2006 02:30 AM
another exercise question luigi40 C# Programming 3 11-28-2005 03:52 PM
A noob question - how to reduce the size of an array? itachi C Programming 2 11-24-2005 01:30 AM


All times are GMT -6. The time now is 09:40 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22