使用指针指针时为什么scanf正常工作?

时间:2016-12-11 03:28:40

标签: c pointers

我想知道为什么这段代码可以正常工作。我假设scanf正在将值赋给指向char的指针的地址。我知道这个表达式是未定义的,但为什么printf使用指针可以打印正确的值?

int main() {
    char* p;
    p = (char*)malloc(sizeof(char));
    scanf("%c", &p);
    printf("%c", p);
    return 0;
}

结果是

c
c

3 个答案:

答案 0 :(得分:1)

p是一个保存内存地址的变量,内存地址肯定长于1个字节。如果在此变量中存储char值,则先前的值(malloc的内存块)将丢失。 printf只需将变量视为char变量并打印其内容即可。如果你怀疑char会被存储在malloc获得的内存块中,那就不是了。

试试这个:

int main() {
    char *p, *q;
    p = q = (char*)malloc(sizeof(char));
    scanf("%c", &p);
    printf("%c\n%c\n", p, *q);
    return 0;
}

答案 1 :(得分:0)

使用scanf(),您将(相当强制地)一个字节存储到一个多于一个字节的变量(sizeof(char *),在64位计算机上可能是8个字节)。使用printf(),然后读取此大小为sizeof(char)的变量(超过一个字节)的一个字节(sizeof(char *),总是按标准一个)并打印出来。您的变量p比存储char所需的空间更多。由于大小不对齐,因此您不确定p将读取printf()的哪个字节。它可能是scanf()写的字节,也可能是垃圾数据。你很幸运,printf()读取scanf()写的相同字节。

如果所有这些听起来有点不确定,那是因为它涉及未定义的行为。您未正确使用scanf()printf(),因此他们无法保证会发生什么。简而言之,不要这样做。

printf()scanf()不对作为参数给出的源/目标执行任何特殊类型检查。他们使用花式指针算法和堆栈上的参数来确定根据需要读取/写入内容的位置。在编译器构建它之后,printf()scanf()不会抱怨。您的编译器应该已经警告您给出的参数类型与格式字符串不匹配。如果没有,您可能有一个坏/旧的编译器,或者您应该使用命令行选项-Wall启用更多警告。

答案 2 :(得分:0)

为了帮助解释其他答案,看起来好像你的目标是做以下事情 - 比较差异,然后再看看其他答案,看看是否有帮助,因为我不确定你还没有清楚你的代码中发生了什么。

int main() {
    char* p = malloc(sizeof(char));
    scanf("%c", p);
    printf("%c", *p);
    return 0;
}