scanf("3c",&c);

scanf("%3c", &c);

My girlfriend CC asked me a question about C programming language today, “What does scanf("%mc", &c) mean?” When I heard this question, I immediately thought that it should resemble printf("%mc", c), which means writing character c in m-chars width to standard output. Therefore, scanf("%mc", &c) should mean reading character c in m-chars width from standard input and I wrote a simple test file as following:

# include<stdio.h>

int main(){
    char c;
    scanf("%3c", &c);
    printf("%c\n", c);
    return 0;
}

Really simple, right? And it passed the compilation perfectly, no errors and no warnings, under gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1). Just run it. However, after I input abc and clicked Enter, I got the following output:

a
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

a was easy to understand, but what was the meaning of the next two lines? It seemed that I got into a big problem. So I googled it and got one possible reason from “*** stack smashing detected ***: ./a.out terminated Aborted (core dumped)” - array inserion. scanf("%3c", &c); tried to write something into unallocated memory space. From Stack smashing detected, we could know scanf("%3c", &c); triggering the protection mechanism used by gcc is the most possible reason for this error.

In conclusion, scanf() just reads something from standard input into memory without checking the buffer overflow. Therefore we must be careful when using it to avoid some unexpected errors.


I tried to see the neighbors of c using the following code.

#include <stdio.h>

int main(){
    char c;
    scanf("%3c", &c);
    char *p = &c;
    printf("%d,%d,%d\n", *(p - 1), *p, *(p + 1));
    return 0;
}

Run it, input abc and click the Enter. I saw:

0,97,-81
  • Where does -81 come from?
  • Why no “terminal”?

With the two questions, I reran the code several times with the same steps. Ans I found that the output was always like 0,91,x where x is an integer approximately between -128 and 127. Moreover, the following code had the same effect with the above, in which I modified scanf("%3c", &c); into scanf("%c", &c);.

#include <stdio.h>

int main(){
    char c;
    scanf("%c", &c);
    char *p = &c;
    printf("%d,%d,%d\n", *(p - 1), *p, *(p + 1));
    return 0;
}
  • Let’s answer the first question. As the memory space behind the pointer p points was unallocated, its value stayed unsure. When we tried to printf its value in decimal, we could see the value between -128 and 127, the decimal domain of an 8-bit.
  • As for the “terminal”, I cannot figure it out. I just created a pointer to c and the error disappeared. Maybe it just didn’t trigger the protection mechanism used by gcc.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章