我最近尝试了一些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
的意思是"一半",即 short
,u
是为了unsigned
。您未能使用正确的格式转换说明符会导致未定义的行为,其中scanf()
覆盖内存中的相邻变量。
另外,请注意,gets()
由于非常危险而被弃用:请不要使用它。改用表现更好的fgets()
。并且永远不要按sizeof (char)
缩放分配,这只是一种非常难以阅读的编写* 1
方式,不会增加任何价值。
因为在 C 中,没有什么能阻止你写入超出特定变量的内存。一切都只是一个地址,知道您可以在该地址之后写入多少字节取决于您,而不是编译器要检查的内容。
短 int 使用的内存字节数比常规 int 少。您分配了一个短整型。然后你要求scanf写一个正常的int.scanf写入分配的内存之外,并覆盖了char *指针的一部分,它恰好位于你的short int之后。这称为未定义行为,因为不知道您可以覆盖什么。指针位于 temp 之后的内存中这一事实是一个巧合。
指针现在指向无效的内存地址,当您尝试访问它时会出现分段错误。
指针实际上只是存储内存地址的另一个整数变量(长整型)。