C语言结构访问元素

C语言结构访问元素,c,C,在这种情况下,我们如何访问元素?我有时会根据创建节点的顺序(即a、b、c先创建x、y、z或x、y、z先创建a、b、c)获得垃圾输出 这里的幕后发生了什么?q是如何访问元素的 *q如何访问p的元素 它是通过char指针来实现的,使用的规则是struct的地址必须与其初始元素的地址匹配(即fieldp.x)。但是,该标准允许编译器在x之后插入填充,因此将1添加到((char*)q)不一定会产生y的地址 您可以按如下方式修复程序: struct Ournode { int a,b,c; cha

在这种情况下,我们如何访问元素?我有时会根据创建节点的顺序(即a、b、c先创建x、y、z或x、y、z先创建a、b、c)获得垃圾输出

这里的幕后发生了什么?q是如何访问元素的

*q
如何访问
p
的元素

它是通过
char
指针来实现的,使用的规则是
struct
的地址必须与其初始元素的地址匹配(即field
p.x
)。但是,该标准允许编译器在
x
之后插入填充,因此将
1
添加到
((char*)q)
不一定会产生
y
的地址

您可以按如下方式修复程序:

struct Ournode {
  int a,b,c;
  char x, y, z;
  int d;
};
int main() {
  struct Ournode p = {3,4,5,'1', '0', 'a' + 2,6};
  struct Ournode *q = &p;
  printf("%c, %c", *((char *)q + 1), *((char *)q + 2));
  printf("%d, %d\n", *((int *)q + 1), *((int *)q +2 ));
  return 0;
}
由于
((char*)q)
指向
int
字段
a
的一部分,因此从这些地址打印
%c
会产生对
int
表示为
char
的部分的实现定义的重新解释。就打印
int
s而言,您应该为技巧添加相同的
偏移量,以抵消潜在填充的结果

注意:我还没有看到在
char
s之间插入填充的编译器,但是我在标准中没有找到任何东西阻止它这样做。如果使用
char x[3]
而不是
char x,y,z
,情况会有所不同,因为数组成员之间不允许填充

q是如何访问元素的

这已经得到了回答,所以我想回答你的另一个问题

在这种情况下,我们如何访问元素?有时,根据创建节点的顺序(即a、b、c先创建x、y、z或x、y、z先创建a、b、c),我会获得垃圾输出

如果您想通过指向该节点的指针
q
访问
struct Ournode
的成员,则有一个操作符
->
可以实现这一点。 您的代码现在将如下所示

printf(
    "%c, %c"
,   *((char *)q + offsetof(struct Ournode, y))
,   *((char *)q + offsetof(struct Ournode, z))
);

仅供参考,您可以将
q
的类型更改为
void*
,并具有相同的输出和可能的问题。所有这些类型转换都很重要,与您看到的输出相关,并且基本上忽略了
q
的指针类型,从而使其不相关。你应该更多地了解铸造的作用(然后避免使用它们,因为它们通常意味着你在做一些有问题的事情,特别是对于初学者)。
printf(
    "%c, %c"
,   *((char *)q + offsetof(struct Ournode, y))
,   *((char *)q + offsetof(struct Ournode, z))
);
int main() {
  struct Ournode p = {3,4,5,'1', '0', 'a' + 2,6};
  struct Ournode *q = &p;
  printf("%d, %d, %d, %c, %c, %c, %d", , q->a, q->b, q->c, q->x, q->y, q->z, q->d );
  return 0;
}