简体   繁体   English

普通的旧C:访问返回结构的函数的成员

[英]Plain old C: accessing member of a function returning struct

Please could you help me with a question of "legitimacy". 请您在“合法性”问题上为我提供帮助。

Assuming that foo() is a function returning a structure, is it officially acceptable to assign a member of the structure directly to a variable, for example 假设foo()是一个返回结构的函数,将结构的成员直接分配给变量是否为正式接受,例如

x = foo().member

Both the GNU-C complier and an embedded C compiler (Keil) accept this without any grumbles but is this actually legitimate according to the official C standard or is it just a relaxed attitude of these particular compilers? GNU-C编译器和嵌入式C编译器(Keil)都接受了这一点,没有任何抱怨,但是根据官方C标准,这实际上是合法的吗?或者仅仅是这些特定编译器的宽松态度? If it's legit, has it always been legit or is it a recent development? 如果这是合法的,那它一直是合法的,还是最近的发展?

Here's an example that compiles and runs OK: 这是一个可以正常运行的示例:

typedef struct
{
    int a;
    int b;
} footype;

footype testfoo(void)
{
    footype n;

    n.a = 1;
    n.b = 2;
    return n;
}

int main()
{
    printf("\nTest = %d\n", testfoo().a);
    return 0;
}

是的,这是标准的C语法。

The testfoo function returns a temporary instance of the structure. testfoo函数返回该结构的临时实例。 This instance can be used at once as show in the example, and the temporary instance is valid until the full expression (ie the printf call in your case) is done. 可以立即使用该实例,如示例中所示,并且临时实例在完成完整表达式(即您的情况下的printf调用)之前一直有效。

It's equivalent to 相当于

{
    footype temp = testfoo();
    printf("\nTest = %d\n", temp.a);
}

It's a standard case of expression evaluation result. 这是表达评估结果的标准案例。
The flow: 流程:

testfoo().a

is a standard C expression where: 是标准的C表达式,其中:

  1. testfoo() result, what the function returns, is in our case a struct footype . 在我们的例子中,函数返回的testfoo()结果是struct footype
  2. Then compiler applies the operator . 然后编译器应用运算符. to the this struct. 到这个结构。
  3. The dot operator access the field a and creates a new result. 点运算符访问字段a并创建一个新结果。
  4. The final expression result is used in the printf() . 最终的表达式结果在printf() This is always valid. 这始终是有效的。
    Ie: 即:

    int *bar(void); //bar is afunnction that returns an int pointer ... i = bar()[10]; //We access the 10th element pointed by bar()

Out of interest I compiled your example and looked at the assembly generated. 出于兴趣,我编译了您的示例并查看了生成的程序集。 First, every compiler can solve this in its own way. 首先,每个编译器都能以自己的方式解决此问题。 I use VC2008. 我使用VC2008。

In your example, the compiler returned the struct in its registers. 在您的示例中,编译器在其寄存器中返回了该结构。

I changed the struct to include a large string, so the compiler would run out of registers. 我将结构更改为包含一个大字符串,因此编译器将用尽寄存器。 It now changed the signature of the function to receive a pointer, and had allocated an instance of the struct on the stack (caller's stackframe), then called the function with a pointer to this struct. 现在,它更改了函数的签名以接收指针,并在堆栈(调用者的stackframe)上分配了该结构的一个实例,然后使用指向该结构的指针调用该函数。 The function copied the result to the struct on the stack using this pointer. 该函数使用此指针将结果复制到堆栈上的结构中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM