%s expects the corresponding argument to be of type
char *, and for
scanf, it had better point to a writable buffer (i.e., not a string literal).
char *str_constant = "I point to a string literal"; char str_buf = "I am an array of char initialized with a string literal"; printf("string literal = %s\n", "I am a string literal"); printf("str_constant = %s\n", str_constant); printf("str_buf = %s\n", str_buf); scanf("%55s", str_buf);
scanf without an explcit field width opens the same buffer overflow exploit that
gets did; namely, if there are more characters in the input stream than the target buffer is sized to hold,
scanf will happily write those extra characters to memory outside the buffer, potentially clobbering something important. Unfortunately, unlike in
printf, you can’t supply the field with as a run time argument:
printf("%*s\n", field_width, string);
One option is to build the format string dynamically:
char fmt; sprintf(fmt, "%%%lus", (unsigned long) (sizeof str_buf) - 1); ... scanf(fmt, target_buffer); // fmt = "%55s"
scanf with the
%s conversion specifier will stop scanning at the first whitespace character; for example, if your input stream looks like
"This is a test"
scanf("%55s", str_buf) will read and assign
str_buf. Note that the field with specifier doesn’t make a difference in this case.