结构有什么特别之处?

81 c arrays struct return return-value

我知道在C中我们不能从函数返回一个数组,而是一个指向数组的指针.但我想知道什么是特殊的东西structs使它们可以通过函数返回,即使它们可能包含数组.

为什么struct包装使以下程序有效?

#include <stdio.h>

struct data {
    char buf[256];
};

struct data Foo(const char *buf);

int main(void)
{
    struct data obj;
    obj = Foo("This is a sentence.");
    printf("%s\n", obj.buf);
    return 0;
}

struct data Foo(const char *buf)
{
    struct data X;
    strcpy(X.buf, buf);
    return X;
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 100

问同一个问题的一个更好的方法是"数组有什么特别之处",因为它是附加了特殊处理的数组,而不是structs.

通过指针传递和返回数组的行为追溯到C的原始实现.数组"衰减"到指针,引起很多混乱,特别是对于刚接触该语言的人.另一方面,结构的行为就像内置类型,例如ints,doubles等.这包括嵌入在其中的任何数组struct,灵活的数组成员除外,它们不会被复制.

  • @jamesqf:`struct Point {short x,y,z;};`.你真的想用指针来移动它们吗?你当然不会以这种方式节省空间. (8认同)
  • @jamesqf我不确定这应该得到回应.如果你认为C不仅仅是汇编,如果你相信没有理由不使用指针,我可能会看到你怎么认为传递结构是无用的.但对于我们其他人来说,他们将C视为一种高级语言(尽管是低级别语言,如HLL一样),并将C类型系统视为一般语言(除了阵列的二级状态之外) ),为什么*不会*我们想传递或返回结构?(BTW,IIRC,K&R1表示结构传递正在进行中,并且在本书发布时它以V7 cc运行.) (6认同)
  • @alk我认为,当结构首次被添加到语言中时,最初有一些限制将它们传递给函数/从函数返回它们,但是这些被明确标记为编译器中的一个缺陷,很快就被纠正了,而不是一个指示想要通过并返回它们有什么不对. (5认同)
  • "确实造成了很多混乱".'x'和'&x'是相同的值/地址是sorta疯狂.newbs得到间接错误并不奇怪:( (3认同)

Sou*_*osh 38

首先,引用C11,章节§6.8.6.4,return陈述,(强调我的)

如果return执行带有表达式的语句,则表达式的将作为函数调用表达式的值返回给调用者.

返回结构变量是可能的(并且正确),因为返回结构.这类似于返回任何原始数据类型(int例如,返回).

另一方面,如果返回一个数组,通过使用它return <array_name>,它实质上返回数组NOTE的第一个元素地址,如果数组是被调用函数的本地数组,它在调用者中变为无效.因此,以这种方式返回数组是不可能的.

因此,TL; DR,没有什么特别的structS,专业是阵列.


注意:

C11再次引用,章节§6.3.2.1,(我的重点)

除非它是运算sizeof符,_Alignof运算符或一元运算&符的操作数,或者是用于初始化数组的字符串文字,否则将类型为''数组'的数组的表达式转换为类型为''的表达式指向类型''的指针指向数组对象的初始元素,而不是左值.[...]


Joh*_*ode 11

struct类型没有什么特别之处; 这就是数组类型有一些特殊之处,可以防止它们直接从函数返回.

struct表达被处理像任何其他非阵列类型的表达式; 它评估的价值struct.所以你可以做的事情

struct foo { ... };

struct foo func( void )
{
  struct foo someFoo;
  ...
  return someFoo;
}
Run Code Online (Sandbox Code Playgroud)

表达式someFoo的计算结果为所述的的struct foo对象; 从函数返回对象的内容(即使这些内容包含数组).

数组表达式的处理方式不同; 如果它不是的操作数sizeof或一元&运算符,或者,如果它不是字面被使用在声明来初始化另一个数组字符串,则表达式转换从类型("衰变")"的阵列T为""指针T" ,表达式的值是第一个元素的地址.

因此,您无法通过函数的值返回数组,因为对数组表达式的任何引用都会自动转换为指针值.