从函数返回结构 - 奇怪的行为 [英] Returning a struct from a function - strange behavior

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

问题描述

大家好,


请查看以下代码:


#include< stdio.h>


typedef struct person {

char name [40];

int age;

} Person;


静态人员make_person(无效);


int main(无效){

printf("%s \ n",make_person()。name);


返回0;

}


静态人物make_person(void){

static Person p = {" alexander",18};


return p;

}


上面的小程序在没有-std = c99选项的情况下编译

(使用gcc 4.2.3)给了我一个警告:

警告:格式?%s?期望类型为?char * ?,但是参数2的类型为

?char [40]?"

并且在执行时也会出现分段错误。


如果我更换行printf(%s \ n,make_person()。name);与

printf("%s \ n",& make_person()。name [0]);一切都按预期工作。


为什么会这样?是不是make_person()。命名指向

数组的第一个元素?


有人回复了这个(在gcc bugzilla中) ,我引用了

答案:


" make_person()。name是一个非左值数组,所以它只衰减到

指针
C99的
,而不是C90。如果您使用-std = c99 / -std = gnu99那么

计划

有效。


该程序没有,但是,已经为C99定义了行为,只有



C1x。在C99中,在调用printf之前,数组的生命周期结束于下一个序列

point,

。在C1x中它反而在包含完整表达式的

评估结束时结束,这是对

printf的调用。


我不认为需要对GCC进行任何更改才能实现这个

特定的C1x要求,因为GCC会丢弃有关

变量的信息

生命周期小于gimplification和树的函数

优化可能会改变这些生命周期,所以它在实践中将会把生命视为无法显示临时的任何地方而不是



现场。


我不明白为什么make_person()。name不是左值数组而且

只衰减到C99的指针。有人可以解释一下这个吗?


这个家伙的意思是什么?在C99中,

数组的生命周期在下一个序列点结束,

之前打电话给printf"?一个函数调用是一个序列点?


我很难理解这个,任何帮助都赞赏

感谢你的时间


PS。我尝试了编译代码而没有警告的lcc编译器/

错误

Hello everyone,

Please take a look at the following code:

#include <stdio.h>

typedef struct person {
char name[40];
int age;
} Person;

static Person make_person(void);

int main(void) {
printf("%s\n", make_person().name);

return 0;
}

static Person make_person(void) {
static Person p = { "alexander", 18 };

return p;
}

The above small program when compiled without the -std=c99 option
(using gcc 4.2.3) gives me a warning:
"warning: format ?%s? expects type ?char *?, but argument 2 has type
?char[40]?"
and also fails with a segmentation fault when executed.

If I replace the line printf("%s\n", make_person().name); with
printf("%s\n", &make_person().name[0]); everything works as expected.

Why does this happen? Isn''t make_person().name a pointer to the
array''s first element?

Someone replied to this (in the gcc bugzilla), I am quoting the
answer:

"make_person().name is a non-lvalue array, so it only decays to a
pointer
for C99, not for C90. If you use -std=c99/-std=gnu99 then the
program
works.

The program does not, however, have defined behavior for C99, only
for
C1x. In C99 the lifetime of the array ends at the next sequence
point,
before the call to printf. In C1x it instead ends at the end of the
evaluation of the containing full expression, which is the call to
printf.

I do not believe any changes to GCC are needed to implement this
particular C1x requirement, since GCC discards information about
variables
lifetimes smaller than a function for gimplification and tree
optimizations that may change those lifetimes, so it will in practice
treat the lifetime as being anywhere it cannot show the temporary not
to
be live."

I can''t understand why make_person().name is not an lvalue array and
only decays to a pointer for C99. Can someone please explain this?

Also what does this guy mean with the line "In C99 the lifetime of the
array ends at the next sequence point,
before the call to printf"? A function call is a sequence point?

I am having a hard time understanding this one, any help appreciated
Thanks for your time

PS. I tried the lcc compiler which compiled the code without warnings/
errors

推荐答案

还有一个问题:


是否在main中创建了任何(Person)变量来保存

make_person()返回值?

如果是这种情况,是吗?返回结构中的所有值都是

复制到上面提到的变量?
One more question:

Is there any (Person) variable created in main to hold the
make_person() return value?
If this is the case, does all the values from the returned struct be
copied to the variable mentioned above?


DiAvOl< dia ... @ freemail.grwrote:
DiAvOl <dia...@freemail.grwrote:

大家好,


请查看以下代码:


#include< stdio.h>


typedef struct person {

* char name [40];

* int age;


}人物;


静态人物make_person(无效);


int main(void){

* printf("%s\ n",make_person()。name);

* return 0;

}


static Person make_person(void){

* static Person p = {" alexander",18};

* return p;

}


上面的小程序在编译时没有

-std = c99选项(使用gcc 4.2.3)给了我一个警告:

"警告:格式? %s吗?期望类型?char * ?,但是

参数2的类型为?char [40]?"

并且在执行时也会出现分段错误。
Hello everyone,

Please take a look at the following code:

#include <stdio.h>

typedef struct person {
* char name[40];
* int age;

} Person;

static Person make_person(void);

int main(void) {
* printf("%s\n", make_person().name);
* return 0;
}

static Person make_person(void) {
* static Person p = { "alexander", 18 };
* return p;
}

The above small program when compiled without the
-std=c99 option (using gcc 4.2.3) gives me a warning:
"warning: format ?%s? expects type ?char *?, but
argument 2 has type ?char[40]?"
and also fails with a segmentation fault when executed.



那是gcc 4.2.3中的一个错误。 [同样的段错误

与-ansi一起发生。]

That''s a bug in gcc 4.2.3 then. [The same segfault
happens with -ansi.]


如果我更换行printf("%s \ n", make_person()。name);

with printf("%s \ n",& make_person()。name [0]);一切

按预期工作。


为什么会这样?
If I replace the line printf("%s\n", make_person().name);
with printf("%s\n", &make_person().name[0]); everything
works as expected.

Why does this happen?



因为gcc 4.2.3中存在错误。

Because there''s a bug in gcc 4.2.3.


Isn't make_person( ).name指向数组的第一个

元素的指针?
Isn''t make_person().name a pointer to the array''s first
element?



因为它不是一元&的操作数。或者sizeof运营商,

是的。

Since it''s not the operand to an unary & or sizeof operator,
yes.


有人回复了这个(在gcc bugzilla中),我是

引用答案:


" make_person()。name是一个非左值数组,因此只有
衰减到C99的指针,而不是对于C90。
Someone replied to this (in the gcc bugzilla), I am
quoting the answer:

"make_person().name is a non-lvalue array, so it only
decays to a pointer for C99, not for C90.



向他们询问章节和经文。并问他们为什么

printf("%s \ n"," hello")并没有因为相同的原因而形成错误。


C89(草稿):


"左值是一个表达式(带有对象

类型或不完整类型除了void之外,

指定一个对象。


除非它是sizeof的操作数

操作员或一元&运算符,或者是一个字符串

literal用于初始化一个字符类型数组,或者

是一个宽字符串文字用于初始化一个数组

与wchar_t兼容的元素类型,一个具有

类型``数组类型''''的左值转换为表达式

有类型``指针键入''''指向数组对象的初始

成员,而不是左值。


C99:


6.3.2.1p1"左值是一个表达式(带有一个对象

类型或void之外的不完整类型)指定

一个对象。"


6.3.2.1p3"除非它是

运算符或一元&运算符的操作数。运算符,或者是一个字符串文字

用于初始化一个数组,一个表达式类型为

??数组类型??转换为类型为
的表达式
??指向类型的指针??这指向数组对象的初始元素

并且不是左值。


仅在C90中明确要求左值。但是在

的情况下,make_person()。name是一个左值。


-

彼得

Ask them for chapter and verse. And ask them why
printf("%s\n", "hello") isn''t ill formed for the same
reason.

C89 (draft):

"An lvalue is an expression (with an object
type or an incomplete type other than void) that
designates an object."

"Except when it is the operand of the sizeof
operator or the unary & operator, or is a character string
literal used to initialize an array of character type, or
is a wide string literal used to initialize an array with
element type compatible with wchar_t, an lvalue that has
type ``array of type '''' is converted to an expression that
has type ``pointer to type '''' that points to the initial
member of the array object and is not an lvalue.

C99:

6.3.2.1p1 "An lvalue is an expression (with an object
type or an incomplete type other than void) that designates
an object."

6.3.2.1p3 "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."

An lvalue is only explicitly required in C90. But in either
case, make_person().name is an lvalue.

--
Peter


2008年10月6日星期一18:34:34 -0700(PDT),DiAvOl< di **** @ freemail.gr>

写道:
On Mon, 6 Oct 2008 18:34:34 -0700 (PDT), DiAvOl <di****@freemail.gr>
wrote:

>还有一个问题:

在main中是否创建了任何(Person)变量来保存
make_person()回报价值?
>One more question:

Is there any (Person) variable created in main to hold the
make_person() return value?



正式来说,这是一个实施细节,标准

没有要求。


实际上,如果你忽略了返回值,答案可能是

no。既然你使用了返回值,答案几乎肯定是

是的。但是有问题的变量是仅为编译器所知的临时构造之一。你没办法

访问它。由于它没有名称,可以说它不是一个变量或对象。

Officially, it is an implementation detail about which the standard
imposes no requirement.

Practically, if you had ignored the return value, the answer might be
no. Since you use the return value, the answer is almost definitely
yes. But the variable in question is one of those temporary
constructs known only to the compiler. There is no way for you to
access it. Since it has no name, one could argue that it is not a
variable or object.


>如果是这种情况,将返回的结构中的所有值复制到上面提到的变量中吗?
>If this is the case, does all the values from the returned struct be
copied to the variable mentioned above?



可能。也许甚至可能。根据你怎么告诉

的差异概念,编译器可能只能确定你只需要
需要会员名称而不是复制会员年龄。


顺便说一句,因为结构是由价值,没有必要

它在你的功能中是静态的。


-

删除电子邮件的del br />

Possibly. Maybe even probably. Under the "how would you tell the
difference" concept, the compiler could probably determine you only
need the member name and not copy the member age.

By the way, since the structure is returned by value, there is no need
for it to be static in your function.

--
Remove del for email


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

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