C指针转换规则

时间:2011-03-27 07:08:04

标签: c pointers unions

我有以下代码:

#include <stdio.h>
#include <stdlib.h>

typedef union stateof stateof;
union stateof 
{
  stateof* foo;
  double* bar;
};

typedef struct hunch hunch;
struct hunch{
  double* first;
  double* second;
};

void main(){
  #define write(x) printf("%d \n",x);

  int* storage = 0;
  stateof* un = (stateof*)&storage;
  un->foo = 300;
  write(storage);

  un->bar = 600;
  write(storage);

  hunch* h = (hunch*)&storage;
  h->first = 1200;
  write(storage);

  h->second = 1600;
  write(storage);
}

该程序的输出是:

300   
600   
1200   
1200

这里发生了什么?

un->{foo,bar}h->{first,second}语句在绝对不指向有效结构时执行是什么意思?在此期间究竟发生了什么,为什么联合的输出与结构的输出不同?

3 个答案:

答案 0 :(得分:6)

您的程序会导致各种未定义的行为。你可以得到任何可以想象的输出。编译此代码时,您的编译器可能会给您各种警告 - 尝试修复它们,您应该朝着更好的方向前进。

假设你有一个正常的系统类型,你可以解释你获得输出的原因:

  1. 修改un->foo会使用值storage覆盖300 - 然后将其打印出来。
  2. 修改un->bar会使用值storage覆盖600 - 然后将其打印出来。
  3. 修改h->first会使用值storage覆盖1200 - 然后将其打印出来。
  4. 修改h->second(危险)用值1600覆盖一些内存,然后再次打印storage - 它仍然是1200

答案 1 :(得分:2)

我将详细描述所有内容。

int* storage = 0; - 在堆栈上创建一个零值的指针(换句话说,指向NULL)。

stateof* un = (stateof*)&storage; - un指向storage的指针位置。因此un指向storage的值,该值现在等于0.

un->foo = 300; - 将{300}分配给storage(让我们考虑storage类似于某些int值,因为事实上这是一个指针并不重要) ,现在storage == 300

un->bar = 600; - 与前一个相同,因为un是一个联合,其所有字段实际上只是一个字段的不同名称(嗯,其union的定义)

h->first = 1200;h->second = 1600;与前面的情况类似,只有一个例外,这里的值被分配给结构中的不同字段(内存中的不同位置)。

write(storage); - 打印storage(指针)的值,但不打印storage指向的值(*storage)。

当然,最后但并非最不重要:从来没有像任何一样的代码! :)

答案 2 :(得分:0)

我们不知道会发生什么。语言标准没有说。

编写程序时,您和编译器之间存在隐含的契约。如果你编写了一个正确的程序,它必须生成一个与源代码完全相同的可执行文件。

使用

等代码时
stateof* un = (stateof*)&storage;

你告诉编译器“我确信&storage实际上指的是一个工会状态。相信我,我知道我在做什么!”。

编译器认为“如果你这样说......”,并采取相应的行动。但是,当你违反合同时,可以自由地做任何事情。我们只是不知道输出是什么,或者是否会有一个输出。