返回包含数组结构 [英] Returning struct containing array

查看:141
本文介绍了返回包含数组结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在GCC 4.4.4下面的简单code段错误

The following simple code segfaults under gcc 4.4.4

#include<stdio.h>

typedef struct Foo Foo;
struct Foo {
    char f[25];
};

Foo foo(){
    Foo f = {"Hello, World!"};
    return f;
}

int main(){
    printf("%s\n", foo().f);
}

更改最后一行到

 Foo f = foo(); printf("%s\n", f.f);

正常工作。当 -std = C99 编译两个版本。我是不是简单地调用未定义的行为,或者有什么东西在标准的改变,这允许code C99下工作?为什么是C89下会崩溃吗?

Works fine. Both versions work when compiled with -std=c99. Am I simply invoking undefined behavior, or has something in the standard changed, which permits the code to work under C99? Why does is crash under C89?

推荐答案

我相信行为无论是在C89 / C90和C99的定义。

I believe the behavior is undefined both in C89/C90 and in C99.

foo的()。˚F是数组类型的前pression,特别是的char [25] C99 6.3.2.1p3说:

foo().f is an expression of array type, specifically char[25]. C99 6.3.2.1p3 says:

除非它是在的sizeof 经营者或一元的操作数
  &安培; 运营商,或者是用于初始化数组文本字符串,
  有型的前pression的阵列的键入的转换为
  前pression,类型为指针的键入的指向初始
  数组对象和元素不是一个左值。如果数组对象
  已注册存储类,行为是不确定的。

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

在该特定情况下(一个阵列是由函数返回的结构的一个元素)的问题是,不存在数组对象。函数结果被返回值,因此调用的结果富()是类型的的结构美孚 foo的()。˚F是类型的值(不是左值)的char [25]

The problem in this particular case (an array that's an element of a structure returned by a function) is that there is no "array object". Function results are returned by value, so the result of calling foo() is a value of type struct Foo, and foo().f is a value (not an lvalue) of type char[25].

这是,据我所知,在C的唯一案例(高达C99),你可以有数组类型的非左值前pression。我想说,试图访问它的行为是不作为不确定,可能是因为标准的(可以理解恕我直言)的作者没有想到这种情况的。你可能会看到不同的行为在不同的优化设置。

This is, as far as I know, the only case in C (up to C99) where you can have a non-lvalue expression of array type. I'd say that the behavior of attempting to access it is undefined by omission, likely because the authors of the standard (understandably IMHO) didn't think of this case. You're likely to see different behaviors at different optimization settings.

新的2011 C标准的补丁通过发明新的存储类这个角落情况。 N1570 (该链接是较晚pre-C11征求意见稿)说,在6.2.4p8:

The new 2011 C standard patches this corner case by inventing a new storage class. N1570 (the link is to a late pre-C11 draft) says in 6.2.4p8:

一个非左值前pression与结构或联合类型,其中
  结构或联合包含数组类型的成员(包括
  递归,所有的成员包含结构和联合)是指
  具有自动存储时间和临时终生的对象的。
  当恩pression进行评估,其初始的寿命开始
  值是前pression的价值。其生命周期结束时,
  包含完整的前pression或完整声明符两端的评估。
  任何试图修改在临时寿命结果的对象
  未定义的行为。

A non-lvalue expression with structure or union type, where the structure or union contains a member with array type (including, recursively, members of all contained structures and unions) refers to an object with automatic storage duration and temporary lifetime. Its lifetime begins when the expression is evaluated and its initial value is the value of the expression. Its lifetime ends when the evaluation of the containing full expression or full declarator ends. Any attempt to modify an object with temporary lifetime results in undefined behavior.

所以程序的行为得到了很好的定义C11。直到你能得到一个C11的编译器上,不过,你最好的选择可能是函数的结果存储在本地对象(假设你的目标是工作code,而不是打破编译器):

So the program's behavior is well defined in C11. Until you're able to get a C11-conforming compiler, though, your best bet is probably to store the result of the function in a local object (assuming your goal is working code rather than breaking compilers):

[...]
int main(void ) {
    struct Foo temp = foo();
    printf("%s\n", temp.f);
}

这篇关于返回包含数组结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆