char *strncpy(char *dest, const char *source, size_t n) {
char *start = dest;
while (n && (*dest++ = *source++)) n--;
// I don't understand from the code below this
// I know I put'\0' at the end of dest.
// But I don't know how if (n) while (--n) works.
if (n) while (--n) *dest++ = '\0';
return start;
}

- 301,070
- 26
- 186
- 335

- 13
- 1
-
Please provide a brief description of what you are trying to do. – kiatng Feb 15 '21 at 05:57
4 Answers
This loops
while (n && (*dest++ = *source++)) n--;
has two sub-expressions in the condition expression.
The first one is the sub-expression n
that can be equivalently rewritten like n != 0
.
So if n is not equal to 0 then the second sub-expression (*dest++ = *source++)
is evaluated that copies character pointed to by the pointer source to the element of the destination array pointed to by the pointer dest
.
You can imaging this sub-expression
(*dest++ = *source++)
as the following sequence of operations
( *dest = *source++, *dest++ != '\0' )
The result of the expression is value of the character that is copied. So if the copied character is not the terminating zero character '\0'
then the logical value of the sub-expression is true. Otherwise it is false because is equal to zero ('\0')
.
So this loop either copies n characters or if a zero-character was encountered then all characters before this zero terminating character including the zero terminating character itself.
The next loop appends the destination string with zeroes until the expression --n
is equal to 0.

- 301,070
- 26
- 186
- 335
That function is a bit obfuscated with how it deals with the value of n
.
But, I suppose you know what if (...) { something; }
works, and that it doesn't need the braces if there's just one statement inside?
if (n) while (--n) *dest++ = '\0';
is just a while
nested inside an if
, it's exactly the same as:
if (n) {
while (--n) {
*dest++ = '\0';
}
}

- 6,221
- 16
- 30
The first while
loop copies at most n
characters from source
to dest
. This loop stops when n == 0
, or (*dest++ = *source++)
evaluates to NUL ('\0'
), meaning the end of the source string has been found.
Then n
is tested to see if there are still expected operations - that is, the caller expected more characters to be copied, but the source
string ended early. The second loop fulfills this by placing NUL bytes, padding dest
to match the size of n
.

- 23,367
- 6
- 42
- 53
The stylistic decisions of this code make it difficult for a newer developer to read. A quick run through a beautifier gives this result (with my own comments added).
//takes a destination string, a source string, and a size (count) of characters to copy
char * strncpy(char * dest, const char * source, size_t n) {
//create a pointer to the start of the destination string
char * start = dest;
//run this loop until one of two things happens:
//- n hits 0, meaning we've copied the required number of characters
//- the assignment operator '=' returns '\0', indicating that we've just copied
// a '\0' into dest - this means we've hit the last character in source.
while (n && ( * dest++ = * source++)) {
n--;
}
//this checks to see if n still has leftover value - if it does, it means that
//source had fewer characters than we were asked to copy
if (n) {
//we will now go through the remaining characters and pad the returned string
while (--n) {
//add '\0' to the return string
* dest++ = '\0';
}
}
return start;
}

- 4,989
- 4
- 17
- 37