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
应该指向结构中第一个元素的地址。为什么通过这样取消引用它,它会返回地址本身呢?
答案 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
正确使用结构是:
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
指向使用int
或unsigned int
类型声明的对象(可选择const
或volatile
个限定符)。some_pointer
指向以前已将int
或unsigned int
写入该位置的动态分配存储空间。某些编译器可能会根据此规则进行优化。有关此优势的更多信息,请see here
即使您的char数组中至少包含sizeof(int)
个字节,编译器仍可能忽略(或更糟糕!)您尝试将其作为int
的别名。尽管如此,它在["真实"人们尝试这个的代码,这就是为什么许多现有代码必须用-fno-strict-aliasing
编译的原因。
NB。如果structure
未正确对齐int
,则可能还存在未定义的行为。
答案 2 :(得分:0)
这里有一个名为structure的数组。它的名字给出了地址。所以你不需要拥有&之前的运营商。
你可以拥有p =& structure [0];或p =结构;