当前位置: 首页 > 面试题库 >

返回包含数组的结构

钱星华
2023-03-14
问题内容

以下是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。我是在简单地调用未定义的行为,还是在标准中进行了某些更改,从而使代码可以在C99下工作?为什么在C89下崩溃?


问题答案:

我相信C89 / C90和C99中的行为均未定义。

foo().f是数组类型的表达式,特别是char[25]。 C99 6.3.2.1p3说:

除非它是 sizeof 运算符或一元 运算符的操作数,或者是用于初始化数组的字符串文字,否则将类型为“ array of
type ”的表达式转换为类型为“ pointer to type
的表达式,指向数组对象的初始元素,并且不是左值。如果数组对象具有寄存器存储类,则该行为是不确定的。

在这种特殊情况下(作为函数返回的结构元素的数组)的问题是没有“数组对象”。函数结果按值返回,因此调用的结果foo()是type 的 struct Foo,并且foo().f是type 的值(不是左值)char[25]

据我所知,这是C语言(最多C99)中唯一可以使用数组类型的非左值表达式的情况。我想说的是,尝试访问它的行为并没有被遗漏所定义,这可能是因为该标准的作者(可以理解的恕我直言)没有想到这种情况。在不同的优化设置下,您可能会看到不同的行为。

新的2011 C标准通过发明新的存储类来修补这种情况。 N1570(链接到最新的C11草案)在6.2.4p8中说:

具有结构或联合类型的非左值表达式,其中结构或联合包含具有数组类型的成员(递归包括所有包含的结构和联合的成员)是指具有自动存储期限和 临时生存期
的对象。它的生命周期从对表达式进行求值开始,并且其初始值为表达式的值。当包含完整表达式或完整声明符的求值结束时,其生存期结束。任何试图使用临时生存期修改对象的尝试都会导致未定义的行为。

因此,程序的行为在C11中得到了很好的定义。但是,直到能够获得符合C11的编译器,最好的选择可能是将函数的结果存储在本地对象中(假设您的目标是工作代码而不是破坏编译器):

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


 类似资料:
  • 我在集合中有大约30条记录,其中几乎25条包含单词。现在,当我尝试使用时,它不会返回任何东西。 下面是我的查询代码: 下面是我的Firestore截图:

  • 问题内容: 我正在尝试使用。我对处理包含数组的C结构感兴趣。考虑以下 并假设我已经将其编译到共享库中了从Python我可以做这样的事情 到目前为止一切顺利:我已经创建了正确的类型,并且一切似乎都正常。但是之后: 我显然缺少了一些东西。该类型是公认的(否则呼叫将抛出一个错误),但不正确初始化。 问题答案: 代码有2个问题(如我在评论中所述): print_array_struct.argtype-

  • 这是我的合约代码。在这里,我试图存储特定行程的坐标。虽然存储信息合约执行良好。但是当我检索数据时,它应该给出坐标数组。但它抛出了一个错误。 原因:'uint256类型的数据不足' 我在这里错过了什么。有没有其他方法来实现我在这里尝试的? 附言:我是固体新手。

  • 我有一个lambda函数,可以获取动态数据库表中的所有项目,如下所示。我想知道是否有一种方法可以在返回语句中包含响应标头以及“scanResults”数组。 在我当前的代码中,我可以包含标题或scan结果数组。我尝试了放置两个返回语句,但那是不正确的代码。有没有办法将它们组合起来?提前感谢您的任何帮助。

  • 问题内容: 在PHP中,如何从包含的脚本返回到包含它的脚本? IE浏览器: 1-主脚本2-应用程序3-包含 基本上,我想从3返回2,return()不起作用。 代码2-应用 问题答案: includeme.php: main.php: 也给出相同的结果 这是PHP鲜为人知的功能之一,但是对于设置非常简单的配置文件来说可能会很好。

  • 我正在将一个函数应用于一个,并返回一个,以便使用 :