在ISO C99中,非左值的数组仍然会衰减为指针,并且可能是下标的,尽管它们可能不会在下一个序列点之后被修改或使用。 (source)
据我所知,此功能允许在函数返回包含数组的结构的情况下进行数组索引,这在C89中是不允许的(http://yarchive.net/comp/struct_return.html)
请您帮助我理解为什么在下一个序列点之后使用/修改它有限制?
答案 0 :(得分:7)
注意,引用的文本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在他的优秀帖子中所描述的那样,可以释放"释放"在当前声明的最后。
NB。 C99的情况并不像Chris的帖子中描述的那么简单,因为以下内容必须有效:
printf("%s %s\n", foo("hello").buf, foo("bye").buf);
我的gcc 4.8安装似乎是正确的 - 适用于-std=c99
,而segfaults适用于-std=c89
。