繁体   English   中英

使用指针访问结构元素

[英]Accessing structure elements using pointers

当下面的程序没有崩溃时,我感到很惊讶。

typedef struct _x {
  int a;
  char b;
  int c;
} x;

main() {
  x *ptr = 0;
  char *d = &ptr->b;
}

根据我的理解, ->运算符优先于&运算符。 所以当我们尝试取消引用NULL指针tr时,我希望程序在下面的语句中崩溃。

char *d = &ptr->b; 

但语句&ptr->b计算为有效地址。 有人可以解释一下我错了吗?

你的期望是没有根据的。 取消引用空指针时,C程序不一定“崩溃”。 当您尝试执行类似的操作时,C程序会出现所谓的未定义行为 未定义的行为可以通过许多不同的方式表现出来。 它可能导致崩溃。 或者它可以产生甚至类似于“工作”程序的东西。 后者显然是你的情况。

但无论如何,你的程序的行为是不确定的。 不,它不会产生一个“有效地址”,因为你似乎错误地相信。 对应于内存中没有对象存在的位置的数字地址无效(当然,空指针值除外)。

您的代码没有崩溃的原因是您实际上没有取消引用指针。 注意表达式

&ptr->b

实际上并没有尝试加载ptrptr->b的内容。 相反,它只是存储它在内存中的位置。 你最终得到的是指向ptr指向的对象的b字段的指针。 这将是地址0之后的几个字节,因此取消引用刚创建的指针将导致段错误。

&ptr->b == sizeof(int) ,表示_x.a (类型为int )之后_x内的b相对于地址*((x*)0)的偏移量。 偏移量为4 (典型值为32位架构)保存在d指针中。 您必须访问d才能获得seg-fault。

计算地址不需要访问内存。 &ptr->b表示“给我ptr指向的结构的b字段的地址。” 这样做不需要查看可能存储在该存储器位置的任何内容。

考虑索引数组而不是结构可能会有所帮助。 C将ptr[5]定义为等价于*(ptr + 5) ,这意味着&(ptr[5])&(*(ptr + 5)) 现在很容易看到&* “取消”并留下(ptr + 5) ,它只涉及指针增量,而不是来自内存的负载。

C使它略微混浊,因为它区分左值和右值。 也就是说,表达式的表达式在表达式的左侧与右侧的表达式区别对待。 给出像x = y;的陈述x = y; ,C编译器将从y的地址加载一个值,并将其存储在x的地址中。 这是区别: y被隐式解除引用,但x不是。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM