Why does C's printf format string have both %c and %s?

CString Formatting

C Problem Overview


Why does C's printf format string have both %c and %s?

I know that %c represents a single character and %s represents a null-terminated string of characters, but wouldn't the string representation alone be enough?

C Solutions


Solution 1 - C

Probably to distinguish between null terminated string and a character. If they just had %s, then every single character must also be null terminated.

char c = 'a';

In the above case, c must be null terminated. This is my assumption though :)

Solution 2 - C

%s prints out chars until it reaches a 0 (or '\0', same thing).

If you just have a char x;, printing it with printf("%s", &x); - you'd have to provide the address, since %s expects a char* - would yield unexpected results, as &x + 1 might not be 0.

So you couldn't just print a single character unless it was null-terminated (very inefficent).

EDIT: As other have pointed out, the two expect different things in the var args parameters - one a pointer, the other a single char. But that difference is somewhat clear.

Solution 3 - C

The issue that is mentioned by others that a single character would have to be null terminated isn't a real one. This could be dealt with by providing a precision to the format %.1s would do the trick.

What is more important in my view is that for %s in any of its forms you'd have to provide a pointer to one or several characters. That would mean that you wouldn't be able to print rvalues (computed expressions, function returns etc) or register variables.

Edit: I am really pissed off by the reaction to this answer, so I will probably delete this, this is really not worth it. It seems that people react on this without even having read the question or knowing how to appreciate the technicality of the question.

To make that clear: I don't say that you should prefer %.1s over %c. I only say that reasons why %c cannot be replaced by that are different than the other answer pretend to tell. These other answers are just technically wrong. Null termination is not an issue with %s.

Solution 4 - C

The printf function is a variadic function, meaning that it has variable number of arguments. Arguments are pushed on the stack before the function (printf) is called. In order for the function printf to use the stack, it needs to know information about what is in the stack, the format string is used for that purpose.

e.g.

printf( "%c", ch );    tells the function the argument 'ch' 
                       is to be interpreted as a character and sizeof(char)

whereas

printf( "%s", s );   tells the function the argument 's' is a pointer 
                     to a null terminated string sizeof(char*)

it is not possible inside the printf function to otherwise determine stack contents e.g. distinguishing between 'ch' and 's' because in C there is no type checking during runtime.

Solution 5 - C

%s says print all the characters until you find a null (treat the variable as a pointer).

%c says print just one character (treat the variable as a character code)

Using %s for a character doesn't work because the character is going to be treated like a pointer, then it's going to try to print all the characters following that place in memory until it finds a null

Stealing from the other answers to explain it in a different way.

If you wanted to print a character using %s, you could use the following to properly pass it an address of a char and to keep it from writing garbage on the screen until finding a null.

char c = 'c';
printf('%.1s', &c);

Solution 6 - C

For %s, we need provide the address of string, not its value.

For %c, we provide the value of characters.

If we used the %s instead of %c, how would we provide a '\0' after the characters?

Solution 7 - C

Id like to add another point of perspective to this fun question.

Really this comes down to data typing. I have seen answers on here that state that you could provide a pointer to the char, and provide a

"%.1s"

This could indeed be true. But the answer lies in the C designer's trying to provide flexibility to the programmer, and indeed a (albeit small) way of decreasing footprint of your application.

Sometimes a programmer might like to run a series of if-else statements or a switch-case, where the need is to simply output a character based upon the state. For this, hard coding the the characters could indeed take less actual space in memory as the single characters are 8 bits versus the pointer which is 32 or 64 bits (for 64 bit computers). A pointer will take up more space in memory.

If you would like to decrease the size through using actual chars versus pointers to chars, then there are two ways one could think to do this within printf types of operators. One would be to key off of the .1s, but how is the routine supposed to know for certain that you are truly providing a char type versus a pointer to a char or pointer to a string (array of chars)? This is why they went with the "%c", as it is different.

Fun Question :-)

Solution 8 - C

C has the %c and %s format specifiers because they handle different types.

A char and a string are about as different as night and 1.

Solution 9 - C

%c expects a char, which is an integer value and prints it according to encoding rules.

%s expects a pointer to a location of memory that contains char values, and prints the characters in that location according to encoding rules until it finds a 0 (null) character.

So you see, under the hood, the two cases while they look alike they have not much in common, as one works with values and the other with pointers. One is instructions for interpreting a specific integer value as an ascii char, and the other is iterating the contents of a memory location char by char and interpreting them until a zero value is encountered.

Solution 10 - C

I have done a experiment with printf("%.1s", &c) and printf("%c", c). I used the code below to test, and the bash's time utility the get the runing time.

    #include<stdio.h>
    int main(){
        char c = 'a';
        int i;
        for(i = 0; i < 40000000; i++){
            //printf("%.1s", &c); get a result of 4.3s
            //printf("%c", c); get a result of 0.67s
        }
        return 0;
    }

The result says that using %c is 10 times faster than %.1s. So, althought %s can do the job of %c, %c is still needed for performance.

Solution 11 - C

Since no one has provided an answer with ANY reference whatsoever, here is a printf specification from pubs.opengroup.com which is similar to the format definition from IBM

> %c

> The int argument shall be converted to an unsigned char, and the resulting byte shall be written.

> %s > The argument shall be a pointer to an array of char. Bytes from the array shall be written up to (but not including) any terminating null byte. If the precision is specified, no more than that many bytes shall be written. If the precision is not specified or is greater than the size of the array, the application shall ensure that the array contains a null byte.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRed BananaView Question on Stackoverflow
Solution 1 - CMaheshView Answer on Stackoverflow
Solution 2 - CLuchian GrigoreView Answer on Stackoverflow
Solution 3 - CJens GustedtView Answer on Stackoverflow
Solution 4 - CAndersKView Answer on Stackoverflow
Solution 5 - CJuan MendesView Answer on Stackoverflow
Solution 6 - CRolandXuView Answer on Stackoverflow
Solution 7 - CtrumpetlicksView Answer on Stackoverflow
Solution 8 - CPhilipView Answer on Stackoverflow
Solution 9 - CGerasimos RView Answer on Stackoverflow
Solution 10 - CRayView Answer on Stackoverflow
Solution 11 - Cuser29053View Answer on Stackoverflow