C指针转换规则

C指针转换规则,c,pointers,unions,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 wri

我有以下代码:

#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);
}
这里发生了什么

un->{foo,bar}
h->{first,second}
语句肯定没有指向有效的结构时,执行它们意味着什么?在这段时间内到底发生了什么?为什么联合的输出与结构的输出不同?

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

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

  • 修改
    un->foo
    会用
    300
    值覆盖
    storage
    ——然后打印出来
  • 修改
    un->bar
    会用
    600
    值覆盖
    storage
    ——然后打印出来
  • 修改
    h->首先
    1200
    值覆盖
    存储
    ——然后打印出来
  • 修改
    h->second
    (危险地)会用
    1600
    值覆盖一些内存,然后再次打印
    storage
    ——仍然是
    1200
  • 您的程序会导致各种未定义的行为。你可以得到任何可以想象的输出。当你编译这段代码时,你的编译器可能会给你各种各样的警告——试着修复它们,你应该朝着更好的方向前进

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

  • 修改
    un->foo
    会用
    300
    值覆盖
    storage
    ——然后打印出来
  • 修改
    un->bar
    会用
    600
    值覆盖
    storage
    ——然后打印出来
  • 修改
    h->首先
    1200
    值覆盖
    存储
    ——然后打印出来
  • 修改
    h->second
    (危险地)会用
    1600
    值覆盖一些内存,然后再次打印
    storage
    ——仍然是
    1200

  • 我将详细描述所有这些

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

    stateof*un=(stateof*)&storage
    -
    un
    指向作为指针的
    存储器的位置。所以
    un
    指向
    存储器的值,该值现在等于0

    un->foo=300
    -将300分配到
    存储
    (让我们考虑
    存储
    类似于某个
    int
    值,因为它实际上是一个指针并不重要),所以现在
    存储==300

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

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

    写入(存储)-打印
    存储
    (指针)的值,但不打印
    存储
    指向(
    *存储
    )的值


    当然,最后但并非最不重要的一点是:永远不要再像那样编写代码了!:)

    我将详细描述所有内容

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

    stateof*un=(stateof*)&storage
    -
    un
    指向作为指针的
    存储器的位置。所以
    un
    指向
    存储器的值,该值现在等于0

    un->foo=300
    -将300分配到
    存储
    (让我们考虑
    存储
    类似于某个
    int
    值,因为它实际上是一个指针并不重要),所以现在
    存储==300

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

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

    写入(存储)-打印
    存储
    (指针)的值,但不打印
    存储
    指向(
    *存储
    )的值


    当然,最后但并非最不重要的一点是:永远不要再像那样编写代码了!:)

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

    当你编写一个程序时,你和编译器之间有一个隐含的契约。如果你写了一个正确的程序,它必须产生一个完全按照源代码所说的执行的可执行文件

    当你使用像

    stateof* un = (stateof*)&storage;
    
    您正在告诉编译器“我确信
    &storage
    实际上指向一个联合状态。相信我,我知道我在做什么!”


    编译器会思考“如果你这么说……”,并相应地采取行动。但既然你已经违反了合同,那么你可以自由地做任何事情。我们只是不知道输出会是什么,或者是否会有输出。

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

    当你编写一个程序时,你和编译器之间有一个隐含的契约。如果你写了一个正确的程序,它必须产生一个完全按照源代码所说的执行的可执行文件

    当你使用像

    stateof* un = (stateof*)&storage;
    
    你是在告诉编译器“我确信