Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

strncpy documentation question

Tags:

c++

c

strncpy

At the following regarding strncpy: http://www.cplusplus.com/reference/clibrary/cstring/strncpy/, it mentions the following:

No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.

What is meant by this sentence?

like image 785
Simplicity Avatar asked Jan 22 '11 14:01

Simplicity


4 Answers

It means that, for example, if your source string is 20 characters plus a null terminator and your strncpy specifies less than 21 characters, the target string will not have a null appended to it.

It's because of the way it works: strncpy guarantees that it will write exactly N bytes where N is the length value passed in.

If the length of the source string (sans null byte) is less than that, it will pad the destination area with nulls. If it's equal or greater, you won't get a null added to the destination.

That means it may not technically be a C string that you get. This can be solved with code like:

char d[11];          // Have enough room for string and null.
strncpy (d, s, 10);  // Copy up to 10 bytes of string, null the rest.
d[10] = '\0';        // Then append null manually in case s was too long.

You allocate 11 bytes (array indexes 0..10), copy up to 10 (indexes 0..9) then set the 11th (index 10) to null.

Here's a diagram showing the three possibilities for writing various-sized strings to a 10-character area with strncpy (d, s, 10) where . represents a null byte:

s              d
-------------  ----------
Hello.         Hello.....
Hello Fred.    Hello Fred
Hello George.  Hello Geor

Note that in the second and third case, no null byte is written so, if you treat d as a string, you're likely to be disappointed in the outcome.

like image 53
paxdiablo Avatar answered Oct 19 '22 08:10

paxdiablo


The string "foo" has 3 characters + 1 null-terminator (it's stored as "foo\0") giving a total length of 4. If you call strncpy with n=3 (or fewer) it won't append a null-terminator to the end of the target string, but will copy only "foo". Attempting to print the resulting string will result in undefined behaviour due to the lack of a null-terminator which signals the end of the string.

You have to be very careful of this and either pass n one greater than the maximum source or add the null-terminator yourself.

like image 5
moinudin Avatar answered Oct 19 '22 09:10

moinudin


That means that it copies the terminating null of the source string, but doesnt add a terminating null if the source string doesnt fit into the destination.

like image 4
thbusch Avatar answered Oct 19 '22 07:10

thbusch


In C strings stored as arrays of char's and they are null-terminated, which means they have an extra 0 appended at the end, which marks the end of the string and could be used later to figure out the string's length. So the string "hello" looks like this in memory:

char hello[] = {'h', 'e', 'l', 'l', 'o', 0};

Normally, when you copy a string, the null character should be copied as well. So the memory needed for the string buffer is its length + 1 (e.g. (strlen(hello) + 1) * sizeof(char)).

Function strncpy allows you to copy only as many characters as it's possible to fit in the provided buffer. In case the buffer you provided is not big enough to hold that extra null, it won't be added. Or if the string is cut, it won't be null-terminated.

char hello[] = "hello"; // 5 characters, 6 bytes long
char hel[3];
strncpy(hel, hello, 3); // hel is {'h', 'e', 'l'}

You should be always careful after calling strncpy, since the result might not be a valid C string. If the string is not null-terminated it's impossible to know its length and most of the string manipulation functions would fail or would do something unexpected.

like image 4
detunized Avatar answered Oct 19 '22 08:10

detunized