如何证明 - > int * pMember =&(pSomeType-> SomeIntMember);

时间:2017-07-30 04:49:35

标签: c++

In this question

提问者提出一个关于#define offsetof(st, m) \ ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )) deference null(0)指针的问题,并且没有段错误。

JaredPar's answer指出:

  

- >运算符在上面使用但它不用于访问该值。   相反,它用于获取值的地址。这里有一个   应该让它更清晰的非宏代码示例

SomeType *pSomeType = GetTheValue();
int* pMember = &(pSomeType->SomeIntMember);
     

第二行实际上不会导致解除引用(实现   依赖)。它只返回SomeIntMember的地址   pSomeType值。

我的问题是如何证明int* pMember = &(pSomeType->SomeIntMember);只是将someIntMember的地址分配给pMember而不引用pSomeType。

有没有iso c ++标准?或者有什么方法吗?

编辑:

虽然我发布的问题是c,我想要c ++答案,所以我将这个问题标记为c ++。

如果c ++标准中有什么内容,那就更好了。

否则,我希望看到一些证明JaredPar结论的东西,例如xaxxon发布了assembly,或者具体的编译器如何实现。

如果答案持有int* pMember = &(pSomeType->SomeIntMember);确实对pSomeType有所帮助,那么为什么offsetof的实现(#define offsetof(st, m) ((size_t) ( (char *)&((st *)(0))->m - (char *)0 )))有效?

UPDATE:

感谢所有的评论和答案,现在我明白#define offsetof(st, m) ((size_t) ( (char*)&((st*)(0))->m - (char)0))是c中的实现之一,而不是c ++中的实现。

另外,我发现了msvc的实现,#define offsetof(s,m) ((size_t)&reinterpret_cast<char const volatile&>((((s*)0)->m))),但它对我来说有点复杂,有人可以表达一下吗?提前致谢。

2 个答案:

答案 0 :(得分:2)

->运算符会导致取消引用。如果a -> b是指针,则(*a).b定义为a

如果人们声称这不是一个解除引用,那么他们要么弄错了,要么使用“#34; dereference&#34;”这个词的一些非标准含义。

在C ++标准中,*的正式名称是间接运算符。单词&#34; dereference&#34;不用作动词;相反,标准表示将*运算符应用于指针会产生一个左值,用于指定指向的对象。

如果&(p->x)不是有效指针,

p会导致未定义的行为。

关于&#34;偏移&#34;编辑时,实现标头中的代码不受语言规则的约束。它们可以包含魔术和非标准的非可移植代码。

答案 1 :(得分:0)

M.M's answer指出时,->运算符 是一个解除引用(如果操作数是指针)。关于这是否解除引用的困惑可能源于相关的内存访问概念。

取消引用指针是将对象放在指向的地址处。或者更准确地说,给定p类型的指针T*,表达式*p是类型T的左值,它引用指向的对象。

内存访问是指发生读取或写入时,分别对应于左值到右值的转换和赋值。如果没有发生,则无法访问内存。

pSomeType->SomeIntMember    // is defined to be...
(*pSomeType).SomeIntMember

*pSomeTypeSomeType的左值,因此其成员SomeIntMemberint的左值。

然后是它的地址。没有左值到右值的转换,也没有分配,因此没有内存访问,如@ xaxxon的评论所示。