我相信C89 / C90和C99中的行为均未定义。
foo().f是数组类型的表达式,特别是
char[25]。 C99 6.3.2.1p3说:
除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串文字,否则将类型为“ array of
type ”的表达式转换为类型为“ pointer to type ”
的表达式,指向数组对象的初始元素,并且不是左值。如果数组对象具有寄存器存储类,则该行为是不确定的。
在这种特殊情况下(作为函数返回的结构元素的数组)的问题是没有“数组对象”。函数结果按值返回,因此调用的结果
foo()是type 的 值
structFoo,并且
foo().f是type 的值(不是左值)
char[25]。
据我所知,这是C语言(最多C99)中唯一可以使用数组类型的非左值表达式的情况。我想说的是,尝试访问它的行为并没有被遗漏所定义,这可能是因为该标准的作者(可以理解的恕我直言)没有想到这种情况。在不同的优化设置下,您可能会看到不同的行为。
新的2011 C标准通过发明新的存储类来修补这种情况。 N1570(链接到最新的C11草案)在6.2.4p8中说:
具有结构或联合类型的非左值表达式,其中结构或联合包含具有数组类型的成员(递归包括所有包含的结构和联合的成员)是指具有自动存储期限和 临时生存期
的对象。它的生命周期从对表达式进行求值开始,并且其初始值为表达式的值。当包含完整表达式或完整声明符的求值结束时,其生存期结束。任何试图使用临时生存期修改对象的尝试都会导致未定义的行为。
因此,程序的行为在C11中得到了很好的定义。但是,直到能够获得符合C11的编译器,最好的选择可能是将函数的结果存储在本地对象中(假设您的目标是工作代码而不是破坏编译器):
[...]int main(void ) { struct Foo temp = foo(); printf("%sn", temp.f);}


