【问题标题】:Pointers in C weird behavior inside a function函数内部的 C 奇怪行为中的指针
【发布时间】:2011-07-18 15:28:51
【问题描述】:

谁能给我解释一下

main()
{
 int *x,y;
 *x = 1;
  y = *x;
 printf("%d",y);
}

当我在 gcc 中编译它时,如何在 main 函数中运行它是可以的,而在不同的函数中运行它不会像下面的函数那样工作?

test()
{
 int *x,y;
 *x = 1;
  y = *x;
 printf("%d",y);
}

【问题讨论】:

  • 您正在取消引用空指针。奇怪的东西比比皆是!
  • 不一定是空指针;一个包含未知垃圾的指针,这更糟。
  • 是的,我正在取消引用一个空指针,但它怎么会在函数 main 中工作??
  • 因为指针的值不同,你正在粉碎、破坏、覆盖别的东西。它也可能在 main 而不是函数中崩溃。您正在取消引用一个未初始化的指针,FWIW 您可能会让飞猴飞出您的鼻子或开始 WW 3。这是“未定义的行为”。
  • 是的,取消引用空指针是正确的,但是你怎么会有奇怪的行为,在主函数中它会工作,但在不同的函数中它不会?

标签: c pointers gcc


【解决方案1】:
int *x,y;
*x = 1;

Undefined Behaviorx 没有任何意义。

这是正确的:

int *x, y, z;
x = &z;
*x = 1;
y = *x;

int *x, y;
x = malloc(sizeof(int));
*x = 1;
y = *x;
//print
free(x);

未定义的行为是未定义的。你无法知道它会如何表现。它似乎可以工作、崩溃、打印不可预测的结果和其他任何东西。或者它可以在不同的运行中表现不同。不要依赖未定义的行为

【讨论】:

  • 未定义意味着它取决于之前堆栈上的内容。这取决于函数的调用方式。
  • 也可以写入解引用表达式(C 的说法:解引用表达式是一个左值,意味着它可以出现在赋值的左侧)
  • @Floste:实际上也许你是对的。从技术上讲,你不是。 @dj buen:我不明白你的意思,对不起。能改一下吗?
  • 我只是想知道 gcc、turbo c 等编译器的实现。
【解决方案2】:

从技术上讲,在标准语言中,由于使用了未初始化的值(指针 x 的值),您调用了所谓的未定义行为。 幕后发生的事情很可能是这样的:您的编译器在堆栈上分配局部变量。调用函数可能会更改堆栈指针,因此不同函数的局部变量位于堆栈上的不同位置。这反过来使未初始化的 x 的值成为当前堆栈帧中该位置的任何值。此值可能不同,具体取决于您调用的函数链的深度。实际值可能取决于很多事情,例如回到程序启动之前调用的整个进程历史。推测实际值可能是什么以及可能发生什么样的错误行为是没有意义的。在 C 社区中,我们将未定义的行为称为甚至有可能生成demons fly out of your nose。它甚至可能启动 WW3(假设安装了适当的硬件)。

说真的,一个物超所值的 C 程序员会非常小心,不要调用未定义的行为。

【讨论】:

  • 这里不需要关闭线程(关闭更多是由非常有信誉的人针对虚假问题执行的紧急程序)。未来的 C 大师访问这个问题可能会有更好的答案。
  • @dj buen - 接受其中一个答案,这会告诉其他所有人您对其中一种解决方案感到满意。
【解决方案3】:

由于 x 是一个指针,它不包含 int 本身,它指向另一个保存该值的内存位置。

我认为您认为声明指向值的指针也会为其保留内存...而不是在 C 中。

如果您在代码中犯了上述错误,如果我给您提供更多关于代码中实际情况的图形表示可能会更好...这是一个常见的新手错误。下面的解释可能看起来有点冗长和基本,但它可能会帮助你的大脑“看到”实际发生的事情。

让我们开始...如果[xxxx] 是存储在 RAM 中的几位中的值,而 [????] 是未知值(在物理内存中),您可以说 X 是正确使用应该是:

x == [xxxx]   ->   [xxxx]
x == address  of   a value (int)

当你在上面写:*x=1 时,你正在改变一个未知的 RAM 区域的值,所以你实际上是在做:

x == [????]  -> [0001]    // address [????] is completely undefined !

事实上,我们甚至不知道 IF 地址 [????] 是否被您的应用程序分配或访问(这是未定义的部分),地址可能指向 任何东西。函数代码、dll地址、文件句柄结构......这一切都取决于编译器/操作系统/应用程序的状态,不能永远依赖。

所以为了能够使用指向 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]

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2020-11-28
    • 2012-05-29
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    相关资源
    最近更新 更多