Is this safe or UB ?
char x[5] = { 'a', 'b', 'c', 'd', 'e' };
printf("%5.5s\n", x);
What is the correct printf format to print a non-zero-terminated string ? (Or what is the format to print the first N characters of a c-string ?)
The behavior is well defined. The argument corresponding to a plain %s conversion specifier must be a pointer to a string (which means, by definition, that it includes a null '\0' terminator), but if a precision is specified the argument doesn't have to be a pointer to a string (i.e., no null terminator as long as the array is long enough).
Quoting the C11 standard draft, N1570 7.21.6.1p8:
Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.
If you want to print the first N characters of a character array, where N isn't a constant, you can use a * to specify that the length is given as a separate argument. For example, given a character array of known length that doesn't contain a null character, you can do this:
const char s[5] = "hello"; /* no terminating null character */
printf("%.*s\n", (int)sizeof s, s);
Note that sizeof works here only because s is an array; if it were a pointer, sizeof would give you the size of a pointer, not the size of the array. Note also that the * requires an argument of type int; since printf is a variadic function, and sizeof yields a value of type size_t, you need the cast in this case.
printf("%.5s", str);
The string does not have to be NUL terminated.
printf("%.*s", 5, str);
will also work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With