【发布时间】:2012-11-21 16:25:20
【问题描述】:
int i = 42;
int *p1 = &i;
int long *p2 = (long*)p1;
这是未定义的行为吗?在 C++ 中,出于某种原因,我认为这是实现定义的行为。
我查看了 C 标准:
C99 6.3.2.3/7 指向对象或不完整类型的指针可能是 转换为指向不同对象或不完整类型的指针。如果 结果指针未正确对齐 57) 对于指向 类型,行为未定义。否则,当再次转换回来时, 结果应与原始指针比较。
57) 一般来说,“正确对齐”的概念是可传递的:如果 指向类型 A 的指针与指向类型 B 的指针正确对齐,这 依次正确对齐指向 C 类型的指针,然后是指针 到类型 A 的指针与指向类型 C 的指针正确对齐。
“正确对齐”一词在实践中是什么意思?在不进入未定义行为的情况下,您如何知道自己是否正确执行了操作?
【问题讨论】:
-
如果您取消引用
p2,这是未定义的行为。原因:你违反了严格别名。 -
int long *p2???这里有什么长的? -
在 32bit arch 上,sizeof(int) == sizeof(long),所以没有区别。在 64 上 - 你会在 long 的另一半有一些垃圾,或者甚至可能留下分配的内存区域,所以再一次 - 没有必要这样做。除此之外,它是正确的。
-
@Krishnabhadra:
int long *p2是一种合法但略显非正统的写作方式signed long int *p2、long *p2、long int *p2或long int signed *p2(这些都是等价的)。跨度> -
在 RISC 机器上的 64 位环境中,
i很有可能在奇数 32 位地址边界上对齐,但long必须在 64 位地址上对齐边界(甚至 32 位地址边界)。因此,在此类系统上,如果您尝试通过p2读取或修改内存,您将获得 SIGBUS。
标签: c type-conversion c99