有人可以向我解释
main()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
当我在gcc中编译它时如何在main函数中运行它是正常的,而在不同的函数中运行它不会像下面的函数一样工作?
test()
{
int *x,y;
*x = 1;
y = *x;
printf("%d",y);
}
答案 0 :(得分:12)
int *x,y;
*x = 1;
Undefined Behavior。 x
并未指出任何有意义的内容。
这是正确的:
int *x, y, z;
x = &z;
*x = 1;
y = *x;
或
int *x, y;
x = malloc(sizeof(int));
*x = 1;
y = *x;
//print
free(x);
未定义的行为是未定义的。你不知道它会如何表现。它似乎工作,崩溃,打印不可预测的结果和其他任何东西。或者它可以在不同的运行中表现不同。不要依赖未定义的行为
答案 1 :(得分:3)
从技术上讲,在标准版中,由于使用了未初始化的值(指针 x 的值),因此调用所谓的未定义行为。 发生了什么事情很可能是这样的:你的编译器在堆栈上分配局部变量。调用函数可能会更改堆栈指针,因此不同函数的局部变量位于堆栈的不同位置。这反过来使未初始化的x的值成为当前堆栈帧中该位置的任何值。此值可以不同,具体取决于您调用的函数链的深度。实际值可能取决于很多事情,例如回到程序启动前调用的整个进程历史记录。没有必要推测实际价值可能是什么以及可能会出现什么样的错误行为。在C社区中,我们将未定义的行为称为甚至可以创建demons fly out of your nose。它甚至可能启动WW3(假设安装了适当的硬件)。
说真的,一个值得她花钱的C程序员会非常小心,不要调用未定义的行为。
答案 2 :(得分:2)
因为x是一个指针,它不包含int本身,所以它指向另一个保存该值的内存位置。
我认为你假设声明指向某个值的指针也会为它保留内存...而不是在C中。
如果你在你的代码中犯了上述错误,那么如果我给你一些关于代码中实际发生的图形表示的话可能会更好......这是一个常见的新手错误。下面的解释可能看起来有点冗长和基本,但它可能有助于你的大脑“看到”实际发生的事情。
让我们开始...如果[xxxx]
是一个存储在RAM中的几位中的值,并且[????]是一个未知值(在物理ram中),你可以说那个为X要正确使用它应该是:
x == [xxxx] -> [xxxx]
x == address of a value (int)
当您在上面写*x=1
时,您正在更改未知RAM区域的值,因此您实际上在做:
x == [????] -> [0001] // address [????] is completely undefined !
事实上,我们甚至不知道你的应用程序分配或访问了IF地址[????](这是未定义的部分),地址可能指向任何。函数代码,DLL地址,文件句柄结构......这一切都取决于编译器/ OS /应用程序状态,并且永远可以依赖。
因此,为了能够使用指向int的指针,我们必须首先为其分配内存,并将该内存的地址分配给x,例如:
int y; // allocate on the stack
x = &y; // & operator means, *address* of"
或
x = malloc(sizeof(int)); // in 'heap' memory (often called dynamic memory allocation)
// here malloc() returns the *address* of a memory space which is at least large enough
// to store an int, and is known to be reserved for your application.
此时,我们知道x拥有正确的内存地址,所以我们只是说它当前设置为[3948]
(并包含一个未知值)。
x == [3948] -> [????]
使用*
运算符,取消引用指针地址(即查找),以存储值 AT 该地址。
*x = 1;
表示:
x == [3948] -> [0001]
我希望这会有所帮助