&((struct name*)NULL - > b)在printf语句中

Him*_*rav 9 c struct casting offsetof

我在一本书中找到了这个代码示例,但是我无法理解printf语句中的表达式.并且这个程序成功编译输出为4.友好建议...

void main(){
    unsigned char c;

    typedef struct name {
      long a;
      int b;
      long c;
    }r;

    r re = {3,4,5};
    r *na=&re;

    printf("%d",*(int*)((char*)na + (unsigned int ) & (((struct name  *)NULL)->b)));
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*gal 9

让我们从最后一行开始:

printf("%d",*(int*)((char*)na + (unsigned int ) & (((struct name  *)NULL)->b)));
Run Code Online (Sandbox Code Playgroud)

让我们解读:

(unsigned int ) & ((    (struct name  *)NULL)->b )
Run Code Online (Sandbox Code Playgroud)

实际上是铸成& (( (struct name *)NULL)->b )了一个unsigned int.

& (( (struct name *)NULL)->b ) 是地址(即它给出一个指针):

((  (struct name  *)NULL)->b )
Run Code Online (Sandbox Code Playgroud)

这实际上是b(as name.b)从NULL(0)的偏移量,它是4个字节(假设a long是4个字节)并转换为int的指针,给出2(假设int是2个字节).

如果不是NULL它本来就是一个指针0xFFFF0000,那么&(ptr->b)本来就是0xFFFF0002.但它更像是&(0 -> b)0x00000002.

所以,(unsigned int ) & (( (struct name *)NULL)->b ) == 2(或者可能是1,或者可能是4,取决于机器).

其余的很简单:*(int*)((char*)na + 2将指向re->b.所以它应该打印4(代码中已初始化的内容r re ={3,4,5};).

PS:即使 (unsigned int ) & (( (struct name *)NULL)->b ) != 2(可能是1,4或8) - 它仍然应该打印4,因为它然后使用相同的偏移来获得值.

  • @Deduplicator是`(((struct name*)NULL) - > b)`未定义的行为?它实际上似乎很适合我.你能指点我指明它的链接吗? (5认同)
  • @MarkSegal:它正在对空指针进行指针运算,这完全是非法的.指针算法仅针对指向有效对象的指针定义,并且仅在它不会超出底层对象的边界时才会定义(尽管明确允许指针通过对象). (2认同)