我正在使用下面的代码来查找某些属性的对齐属性。我知道存储NULL
指针是定义的行为,指针操作也是定义的行为,只有未引用NULL(和其他无效值)指针才会调用未定义的行为。我的问题很简单:->
是否暗示未引用指针(因此在下面的代码中导致未定义的行为)?
#include <iostream>
void f(void *p)
{
std::cout << p << std::endl;
}
struct X
{
int a;
int b;
};
struct Y
{
int a[2];
int b;
};
int main()
{
X *x = NULL;
Y *y = NULL;
f(&x->b);
f(&y->b);
}
答案 0 :(得分:2)
->
运算符是*
和.
运算符的组合。对于
X *x = (struct *)malloc(sizeof(struct));
f(&x->b);
它在x
上执行间接寻找它指向的结构,然后选择结构的b
成员。它类似于呼叫
f( &(*x).b ); // which is same as f( & ( (*x).b ) );
由于在您的情况下x
是NULL
指针,因此取消引用NULL
指针会调用未定义的行为:
C ++ 11:8.3.2参考文献(p4):
注意:特别是,在一个定义良好的程序中不能存在空引用,因为创建这样一个引用的唯一方法是将它绑定到取消引用空指针获得的“对象”,导致未定义的行为。
答案 1 :(得分:1)
有问题的代码并非未定义的行为(虽然它有点不同寻常)。代码实际上是在offsetof()
的调用中执行穷人的f()
,您将b
的结构偏移量传递给该函数。由于您正在计算x->b
的地址,因此不会取消引用NULL指针。您没有通过NULL指针加载x->b
的内容。
为什么上面的代码(相当于offsetof
)不是未定义的行为的引用,C ++ spec (draft 2012-01-16),第427页,声明:
宏
offsetof(type, member-designator)
在本国际标准中接受一组受限制的类型参数。如果type不是标准布局类(第9节),则结果是未定义的。
上面代码中的用法是定义的,因为它使用的是标准布局结构类型(struct X
和struct Y
)。