-1
char c;
printf("%d", scanf("%s", &c)); // prints 1  
printf("%d", scanf("%c", &c)); // prints 1

I do not understand why both these statements prints the same value 1?

As far as I know, scanf() returns the number of input items successfully matched and assigned or even zero in the event of an early matching failure. Then is this not the case of mismatching?

What did I miss here?

Spikatrix
  • 20,225
  • 7
  • 37
  • 83

3 Answers3

6

Both the format specifiers %c and %s expect an argument of type char* when used in scanf family of functions.

The difference is that use of %c will read at most one character to it while use of %s will read all non-whitespace characters it finds. It will also add a terminating null character to the pointer when %s is used.

Given

char c;

Using

scanf("%s", &c);

is a problem since &c has only one valid character that can be written to. Hence, it leads to use of memory that the program is not supposed to, which in turn leads to undefined behavior.

The fact that

printf("%d", scanf("%s", &c))

prints 1 instead of crashing is a matter of bad luck. It would have been nice had the program crashed. Then you would know that the program is wrong.

Spikatrix
  • 20,225
  • 7
  • 37
  • 83
R Sahu
  • 204,454
  • 14
  • 159
  • 270
5

%s and %c are used for different types

is incorrect. They both expect the same type: char *.


"%c" expects a char * that points to 1 char.

"%s" expects a char * that points to an array big enough for the string. This needs to be at least 2 char. OP code likely writes past c. It is undefined behavior to write past the variable's space.


Instead

char s[10];
printf("%d", scanf("%9s", s));
char c;
printf("%d", scanf("%c", &c));
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
3

With a definition like

char c;

using

scanf("%s", &ch);  // "" s added

causes undefined behavior.* Then, the output cannot be justified in any way.


Note: %s format specifier expects the corresponding argument to be a pointer to a char array of sufficient length. Otherwise, there will be memory boundary overrun, which will cause UB.

To quote C11 standard, chapter §7.21.6.2, related to %s format specifier,

[...] the corresponding argument shall be a pointer to the initial element of a character array large enough to accept the sequence and a terminating null character, which will be added automatically.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261