c语言 - 在gets(指针)更改字符指针的值后,scanf("%d",无符号短整型)中的格式说明符错误,但为什么?



我最近尝试了一些C编程,偶然发现了以下问题。我使用的是 NetBeans 7.4 64 IDE 和 MinGW 32 位。这是一个简短的示例代码,突出了我的问题:

int main(void) {
    unsigned short int temp;
    char *pointer;
    pointer = malloc(12 * sizeof(char));
    printf("The pointers value is %d n", (int)pointer);
    printf("Type a short string:n");
    gets(pointer);
    printf("The pointers value is %d n", (int)pointer);
    printf("Type an int: n");
//This line changes the char pointer to an apparently random value
    scanf("%d", &temp);
//Segmentation fault upon this point
    printf("The pointers value is %d n", (int)pointer);
//And here as well
    free(pointer);

    return (EXIT_SUCCESS);
}

在扫描之前一切都很好。get 读取的字符串将写入指针指向的内存空间。但是在处理 scanf 之后,指针的值会更改,以便指针指向任何空间。因此,不仅我的字符串丢失了,而且在尝试访问/释放不属于我的程序的内存时,我也会遇到分段错误。

值变化显然是随机的。每次调试此程序时,指针都会更改为另一个值。

我已经推断出无符号的短 int 有问题,或者更确切地说是我的 scanf 中的格式说明符错误(%d 而不是 %hu)。如果我将无符号的短 int 更改为 int 或使用 %hu 作为说明符,一切正常。所以有解决方案。

但我仍然很好奇指针为什么以及这个错误如何影响。谁能帮我?

程序具有未定义的行为。

你需要告诉scanf()只有一个整数的空间,否则它怎么知道将数字存储为哪个大小?

更改为:

scanf("%hu", &temp);

其中h的意思是"一半",即 shortu是为了unsigned。您未能使用正确的格式转换说明符会导致未定义的行为,其中scanf()覆盖内存中的相邻变量。

另外,请注意,gets()由于非常危险而被弃用:请不要使用它。改用表现更好的fgets()。并且永远不要按sizeof (char)缩放分配,这只是一种非常难以阅读的编写* 1方式,不会增加任何价值。

因为在 C 中,没有什么能阻止你写入超出特定变量的内存。一切都只是一个地址,知道您可以在该地址之后写入多少字节取决于您,而不是编译器要检查的内容。

短 int 使用的内存字节数比常规 int 少。您分配了一个短整型。然后你要求scanf写一个正常的int.scanf写入分配的内存之外,并覆盖了char *指针的一部分,它恰好位于你的short int之后。这称为未定义行为,因为不知道您可以覆盖什么。指针位于 temp 之后的内存中这一事实是一个巧合。

指针现在指向无效的内存地址,当您尝试访问它时会出现分段错误。

指针实际上只是存储内存地址的另一个整数变量(长整型)。

最新更新