June 3, 2023

Using printf with the %s formatter in C

%s formatter

The %s formatter allows printing a c-string using printf. For example:

const char my_c_string[] = "mytext";
printf("printing string: %s", my_c_string);

Result:

> printing string: mytext

The contents of my_c_string get inserted into the printed text where %s is located.

C-string length and the nul terminating character

The above example makes use of a string literal. String literals are constructed using text inside double quotes (e.g. "any text"). String literals implicitly include an additional nul character at the end of the string which is used to indicate the end of the string, without it printf and other functions reading c-strings will not know the length of the string.

This additional nul terminator character takes the value 0 in memory and makes the length of the string 1 character longer. sizeof(my_c_string) will return a length of 7 instead of 6. In memory my_c_string will look like this:

(relative) Byte position0123456
charactermytext\0
raw value1091211161011201160
Contents of const char my_c_string[] = "mytext" in memory

Why is printf outputting additional garbage text?

Because the nul character is implicit and there is no indication from reading the code that it exists, it is a common programmer's error to forget to add the nul terminating character to non-literal strings constructed programatically. Failing to include the nul terminator will result in functions like printf continuing to use memory beyond the end of the string. It will only stop reading from memory when is encounters the value 0 in memory. Aside from printing extra data erroneously this, can cause all kinds of issues including crashing the entire application.

Combined example

A quick example of %s, %d and %c combined. Below is similar to a real-world example for printing a log or debug statement for messages sent to an exernal device.

const char msg_string[] = "Complete";
int msg_id = 12839;
char rw_mode = 'R';
printf("Message status: %s, id = %d, R/W mode = %c", msg_string, msg_id, rw_mode);

Result:

> Message status: Complete, id = 12839, R/W mode = R
© Copyright 2022 by FirmlyEmbedded
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram