C 非左值数组和序列点限制

C 非左值数组和序列点限制,c,C,在ISO C99中,非左值的数组仍然会衰减为指针,并且可以被下标,尽管它们可能不会在下一个序列点之后被修改或使用。() 我知道,在函数返回包含数组的结构的情况下,此功能允许数组索引,这在C89()中是不允许的 请您帮助我理解为什么在下一个序列点之后对其使用/修改有限制?注意,OP引用的文本来自GCC文档。C99中支持该报价的相关文本为: C99 6.5.2.2/5 如果试图修改函数调用的结果或在下一次调用后访问它 序列点,行为未定义 从前言的变化列表中也可以看出: 数组到指针的转换不限于左值 我

在ISO C99中,非左值的数组仍然会衰减为指针,并且可以被下标,尽管它们可能不会在下一个序列点之后被修改或使用。()

我知道,在函数返回包含数组的结构的情况下,此功能允许数组索引,这在C89()中是不允许的


请您帮助我理解为什么在下一个序列点之后对其使用/修改有限制?

注意,OP引用的文本来自GCC文档。C99中支持该报价的相关文本为:

C99 6.5.2.2/5

如果试图修改函数调用的结果或在下一次调用后访问它 序列点,行为未定义

从前言的变化列表中也可以看出:

数组到指针的转换不限于左值

我没有要比较的C89文本,但是数组到指针转换的C99描述(6.3.2.1/3)没有提到数组作为左值的任何限制。另外,C99中关于下标的部分(6.5.2.1/2)讨论了将表达式下标为后缀表达式,它也没有提到左值


考虑以下代码:

struct foo
{
     char buf[20];
};

struct foo foo(char const *p) { struct foo f; strcpy(f.buf, p); return f; }

int main()
{
     char *hello = foo("hello").buf;
     char *bye = foo("bye").buf;

     // other stuff...

     printf("%s\n", hello);
     printf("%s\n", bye);
}
指针
hello
bye
指向哪里?本子句的目的是说明编译器不必为了使这些指针无限期地保持有效而将所有返回的对象都挂在内存中的某个位置

相反,
hello
仅在下一个
之前有效在这种情况下(或通常是下一个序列点)。这使得编译器可以自由地实现按值返回的结构作为隐藏指针参数,正如Chris Torek在他的优秀文章中所描述的,可以在当前语句的末尾“释放”

注意。C99的情况并不像Chris的帖子中描述的那么简单,因为以下几点必须要起作用:

printf("%s %s\n", foo("hello").buf, foo("bye").buf);

尽管如此,我的GCC4.8安装似乎是正确的,它与
-std=c99
一起工作,与
-std=c89
一起工作。我受阻了。在ISO C99标准中,哪里有确切的引用,因为我在任何地方都找不到。如果你要引用标准,请张贴小节,如果需要,请张贴段落标记,从哪里引证。@MattMcNabb Forward p7,我看到的是你的引证,而不是OP的(我也没想到,因为我非常熟悉标准中的“衰退”频率)。谢谢你的来信。(+1)你的答案。@WhozCraig更新了我的帖子w参考资料