struct数组的别名为int

时间:2014-11-03 04:45:48

标签: c arrays pointers strict-aliasing

struct test
{
    char member1;
    char member2;
};

int main(void)
{
    struct test structure[] = {'h', 'i'};
    static void* p = &structure;

    printf("%i", *((int*)p));

    return 0;
}

我们都知道structure应该指向结构中第一个元素的地址。为什么通过这样取消引用它,它会返回地址本身呢?

3 个答案:

答案 0 :(得分:5)

您的代码表现出未定义的行为。

您正在投射structure *以键入int *并取消引用。当(大多数)int的大小更大时,您正在访问离线内存。 (这是一个原因,还有一些原因)

+---+---+---+---+
| h | i | ? | ? |
+---+---+---+---+
Print as int: ? ? i h if machine is little endian

In ascii coding
+---+---+---+---+
| 68| 69| ? | ? |
+---+---+---+---+
Print as int: ?? ?? 69 68

Live code here

正确使用结构是:

struct test s1   = {'h', 'i'};
struct test s2[] = { {'t', 'o'}, {'d', 'o'} };

printf("s1   : %c, %c\n", s1.member1, s1.member2);
printf("s2[0]: %c, %c\n", s2[0].member1, s2[0].member2);
printf("s2[1]: %c, %c\n", s2[1].member1, s2[1].member2);

答案 1 :(得分:1)

由于违反严格别名规则而导致未定义的行为。

通过表达式*(int *)some_pointer阅读时,它仅在以下情况下有效:

  • some_pointer指向使用intunsigned int类型声明的对象(可选择constvolatile个限定符)。
  • some_pointer指向以前已将intunsigned int写入该位置的动态分配存储空间。

某些编译器可能会根据此规则进行优化。有关此优势的更多信息,请see here

即使您的char数组中至少包含sizeof(int)个字节,编译器仍可能忽略(或更糟糕!)您尝试将其作为int的别名。尽管如此,它在["真实"人们尝试这个的代码,这就是为什么许多现有代码必须用-fno-strict-aliasing编译的原因。

NB。如果structure未正确对齐int,则可能还存在未定义的行为。

答案 2 :(得分:0)

这里有一个名为structure的数组。它的名字给出了地址。所以你不需要拥有&之前的运营商。

你可以拥有p =& structure [0];或p =结构;