首页 > 解决方案 > 具有自动存储持续时间的变量的地址可以在其定义中使用吗?

问题描述

是否允许在其定义的右侧获取对象的地址,foo()如下所示:

typedef struct { char x[100]; } chars;

chars make(void *p) {
  printf("p = %p\n", p);
  chars c;
  return c;
}

void foo(void) {
  chars b = make(&b);
}

如果允许,对它的使用是否有任何限制,例如,打印是否可以,我可以将它与另一个指针进行比较等吗?

在实践中,它似乎可以在我测试的编译器上编译,大多数时候(但并非总是)具有预期的行为,但这远非保证。

标签: clanguage-lawyerc11

解决方案


要回答标题中的问题,请记住您的代码示例,是的,可以。C 标准在§6.2.4中说了这么多:

对象的生命周期是程序执行期间保证为其保留存储的部分。一个对象存在,有一个不变的地址,并在其整个生命周期中保留其最后存储的值。

对于这样一个没有可变长度数组类型的对象,它的生命周期从进入与其关联的块开始,直到该块的执行以任何方式结束。

所以是的,您可以从声明点获取变量的地址,因为该对象此时具有地址并且它在范围内。一个精简的例子如下:

void *p = &p;

它的用途很小,但完全有效。

至于你的第二个问题,你能用它做什么。我通常可以说在初始化完成之前我不会使用该地址来访问对象,因为初始化程序中表达式的评估顺序未指定(第 6.7.9 节)。你可以很容易地发现你的脚被击中了。

这确实发生的一个地方是在定义各种需要自引用的表格数据结构时。例如:

typedef struct tab_row {
  // Useful data
  struct tab_row *p_next;
} row;

row table[3] = {
  [1] = { /*Data 1*/, &table[0] },
  [2] = { /*Data 2*/, &table[1] },
  [0] = { /*Data 0*/, &table[2] },
};

推荐阅读