储存临时工 [英] storage for temporaries

查看:69
本文介绍了储存临时工的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过查看

他们的地址来检查临时对象的存在。诀窍是创建一个包含

数组作为其第一个成员的结构。在表达式中,数组rvalue

被转换为指向其第一个成员的指针。由于这个地址

也是数组的地址,那就是

结构的地址,我得出结论,这也是临时的地址

存储结构(r)值。


我知道Heisenberg效应,即。如果没有观察者

(.a运算符),操作数表达式

的实际行为可能会有所不同。有些行为无法衡量,例如,b $ b b。在表达式'x = f()''中,不可能检查`f()''

是否直接返回x,或者返回临时(或其他)对象,

然后被复制到'x''(我当然可以分析一下

列表,但我想只依赖于可见行为)。

我不会尝试修改任何东西。


我希望你回答我的问题并回顾我的结论。

代码是最后,连同como和gcc的输出。

此代码仅在C99模式下编译。


1.对于某些大型显而易见临时数据编译器

有时必须保留一些内存。标准

对临时值的存储有什么看法?是否定义了(C& V),

未定义或未指定?标准对我程序的输出说了什么?


2.表达式`f()。a [0]'有效吗?

函数调用(或产生右值的任何其他运算符)的结果的值是

访问,但是没有序列点,所以没有'''似乎

是该领域的一个明确的UB。 OTOH它是未定义的行为如果

指针(f()。a + 0)具有无效值(6.5.3.2p4)。即使对于

某些原因它是有效的并且没有对象,那么它是未定义的

行为如果左值`f()。a [0]' '

评估时不指定对象(6.3.2.1p1)。无论如何,看起来答案取决于对于右边界的临时物品是否是一个物体,是否需要




3.如果是sfunc_static() (下面)临时

的地址可能与静态对象相同,因为修改fn调用的结果

会引发UB,因此没有什么可以 ;保护"


4.类似的论点适用于=运算符(地址val可以

与s1相同)。 (条件和逗号运算符
gcc输出中的
重用操作数对象存储的值。)


5. Const对象存储总是可以作为存储重用它的价值是
,因为如果该对象被修改则为UB。

=== c_temp_obj.c =============== =======================

#include< stdio.h>


#define PRINT(msg,ptr)printf("%s:\ t%p \ n",msg,(void *)(ptr))


struct s {int a [1]; };


struct s sfunc()

{

struct ss = {0};

PRINT(fn,sa); / *内部变量的地址* /

返回s;

}

static struct s sfunc_static_obj = {0};


/ * sfunc_static()声明为内联,因此不需要

通过临时* /

内联静态返回

struct s sfunc_static()

{

PRINT(" inside fn",sfunc_static_obj.a); / *静态对象的地址* /

返回sfunc_static_obj;

}


内联静态

struct s sfunc_ptrarg(struct s * ps)

{

PRINT(" fn",(* ps).a);

返回* ps;

}


int main()

{

struct s s1 = {0},s2 = {0};

const struct s sc = {0};


puts(" \ n *& :");

PRINT(" s1",& s1);

PRINT(" *& s1",(*& s1)。一个); / *控制代码,预计等于* /


puts(&\\; \ n函数调用:");

PRINT(" fn return", sfunc(A))。 / *临时地址* /


put(" \ nnfunction call(static object):");

PRINT(" fn return",sfunc_static()。a); / *临时的地址* /


put(" \ nnfunction call(through argument):");

PRINT(" s1" ;,s1.a);

PRINT(" fn return",sfunc_ptrarg(& s1).a); / *临时地址* /


puts(&\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ a);

PRINT(" s2",s2.a);

PRINT(" val",(s1 = s2).a); / *临时的地址* /


put(" \ nnconditional operator:");

PRINT(" s1",s1。 a);

PRINT("?:",(1?s1:s2).a);


puts(" \ nncomma operator:");

PRINT(" s1",s1.a);

PRINT("(,)",(0,s1)。 a);


puts(" \ ncomma operator,const object:");

PRINT(" sc",sc.a) ;

PRINT("(,)",(0,sc).a);

返回0;

}

=== out.como ====================================== ====


*&:

s1:0xbffffa44

*& s1:0xbffffa44


函数调用:
$ f $ b里面fn:0xbffffa00

fn返回:0xbffffa38


函数调用(静态)对象):
$ f $ b里面fn:0x8049830

fn返回:0xbffffa34


函数调用(通过参数):
fn:0xbfff中
s1:0xbffffa44

fa44

fn return:0xbffffa30

赋值运算符:

s1:0xbffffa44

s2:0xbffffa40

val:0xbffffa2c


条件运算符:

s1:0xbffffa44

?:: 0xbffffa28


逗号运算符:

s1:0xbffffa44

(,):0xbffffa24


逗号运算符,const对象:

sc:0xbffffa3c

(,):0xbffffa20

=== out.gcc ====== =====================================


* &:

s1:0xbffff224

*& s1:0xbffff224


函数调用:

里面fn:0xbffff1e0

fn返回:0xbffff218

函数调用(静态对象):
$ f $ b里面fn:0x80499f4

fn return:0xbffff214


函数调用(通过参数):

s1:0xbffff224
$ f $ b里面的fn :0xbffff224

fn return:0xbffff210


赋值运算符:

s1:0xbffff224

s2:0xbffff220

val:0xbffff20c


条件运算符:

s1:0xbffff224

?:: 0xbffff224

逗号运算符:

s1:0xbffff224

(,):0xbffff224

逗号运算符,const对象:

sc:0xbffff21c

(, ):0xbffff21c

-

Stan Tobias

mailx`echo si *** @FamOuS.BedBuG.pAlS.INVA LID | sed s / [[:upper:]] // g`

I''m examining the existence of temporary objects by looking at
their addresses. The trick is to create a structure that contains
an array as its first member. In an expression the array rvalue
is converted to a pointer to its first member. Since this address
is also the address of the array, and that is the address of the
structure, I conclude that this is also the address of the temporary
storage for the structure (r)value.

I''m aware of "Heisenberg effect", ie. in absence of an observer
(".a" operator) the actual behaviour of the operand expressions
might be different. Some behaviours are impossible to measure,
eg. in expression `x = f()'' it''s impossible to check if `f()''
returns directly into `x'', or into a temporary (or other) object,
which is then copied into `x'' (I could of course analyze the assembly
listing, but I want to rely only on visible behaviour).
I don''t attempt to modify anything.

I would like you to answer my questions and review my conclusions.
The code is at the end, together with the output for como and gcc.
This code compiles only in C99 mode.

1. It is obvious that for some large temporary data a compiler
must sometimes reserve some memory. What does the Standard
say about storage for temporary values? Is it defined (C&V),
undefined or unspecified? What does the Standard say about
the output from my program?

2. Is the expression `f().a[0]'' valid? Value of the result of
function call (or any other operator that yields an rvalue) is
accessed, but there''s no sequence point, so there doesn''t seem to
be an explicit UB in that area. OTOH it is undefined behaviour if
the pointer (f().a + 0) has invalid value (6.5.3.2p4). Even if for
some reason it is valid and there''s no object, then it is undefined
behaviour if the lvalue `f().a[0]'' does not designate an object when
evaluated (6.3.2.1p1). Anyway, it seems like the answer depends
on whether the temporary thingy for the rvalue is an object or not.

3. In case of sfunc_static() (below) the address of the temporary
could be the same as the static object, because modifying the result
of a fn call raises UB, therefore there is nothing to "protect".

4. Similar argument applies to "=" operator (address "val" could
be the same as that of "s1"). (Conditional and comma operators
in gcc output reuse the operand object storage for the value.)

5. Const object storage can always be reused as storage for its
value, because it is UB if that object is modified.
=== c_temp_obj.c ======================================
#include <stdio.h>

#define PRINT(msg, ptr) printf("%s: \t%p\n", msg, (void*)(ptr))

struct s { int a[1]; };

struct s sfunc()
{
struct s s = {0};
PRINT("inside fn", s.a); /* address of internal variable */
return s;
}
static struct s sfunc_static_obj = {0};

/* sfunc_static() is declared inline so that there is no need
to return through a temporary */
inline static
struct s sfunc_static()
{
PRINT("inside fn", sfunc_static_obj.a); /* address of the static object */
return sfunc_static_obj;
}

inline static
struct s sfunc_ptrarg(struct s *ps)
{
PRINT("inside fn", (*ps).a);
return *ps;
}

int main()
{
struct s s1 = {0}, s2 = {0};
const struct s sc = {0};

puts("\n*&:");
PRINT("s1", &s1);
PRINT("*&s1", (*&s1).a); /* control code, expected equal */

puts("\nfunction call:");
PRINT("fn return", sfunc().a); /* address of the temporary */

puts("\nfunction call (static object):");
PRINT("fn return", sfunc_static().a); /* address of the temporary */

puts("\nfunction call (through argument):");
PRINT("s1", s1.a);
PRINT("fn return", sfunc_ptrarg(&s1).a); /* address of the temporary */

puts("\nassignment operator:");
PRINT("s1", s1.a);
PRINT("s2", s2.a);
PRINT("val", (s1 = s2).a); /* address of the temporary */

puts("\nconditional operator:");
PRINT("s1", s1.a);
PRINT("?:", (1?s1:s2).a);

puts("\ncomma operator:");
PRINT("s1", s1.a);
PRINT("(,)", (0,s1).a);

puts("\ncomma operator, const object:");
PRINT("sc", sc.a);
PRINT("(,)", (0,sc).a);
return 0;
}
=== out.como ==========================================

*&:
s1: 0xbffffa44
*&s1: 0xbffffa44

function call:
inside fn: 0xbffffa00
fn return: 0xbffffa38

function call (static object):
inside fn: 0x8049830
fn return: 0xbffffa34

function call (through argument):
s1: 0xbffffa44
inside fn: 0xbffffa44
fn return: 0xbffffa30

assignment operator:
s1: 0xbffffa44
s2: 0xbffffa40
val: 0xbffffa2c

conditional operator:
s1: 0xbffffa44
?:: 0xbffffa28

comma operator:
s1: 0xbffffa44
(,): 0xbffffa24

comma operator, const object:
sc: 0xbffffa3c
(,): 0xbffffa20
=== out.gcc ===========================================

*&:
s1: 0xbffff224
*&s1: 0xbffff224

function call:
inside fn: 0xbffff1e0
fn return: 0xbffff218

function call (static object):
inside fn: 0x80499f4
fn return: 0xbffff214

function call (through argument):
s1: 0xbffff224
inside fn: 0xbffff224
fn return: 0xbffff210

assignment operator:
s1: 0xbffff224
s2: 0xbffff220
val: 0xbffff20c

conditional operator:
s1: 0xbffff224
?:: 0xbffff224

comma operator:
s1: 0xbffff224
(,): 0xbffff224

comma operator, const object:
sc: 0xbffff21c
(,): 0xbffff21c

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`

推荐答案

2005年7月21日星期四09:30:04 +0000,S .Tobias写道:
On Thu, 21 Jul 2005 09:30:04 +0000, S.Tobias wrote:
我正在通过查看他们的地址来检查临时对象的存在。诀窍是创建一个包含数组作为其第一个成员的结构。在表达式中,数组rvalue
将转换为指向其第一个成员的指针。由于这个地址
也是数组的地址,那就是
结构的地址,我得出结论,这也是结构临时存储的地址(r)价值。

我知道海森堡效应,即。如果没有观察者
(.a运算符),操作数表达式的实际行为可能会有所不同。有些行为无法衡量,例如。在表达式'x = f()''中,不可能检查`f()''
是直接返回到'x'',还是直接返回到临时(或其他)对象,
然后将其复制到x中(我当然可以分析程序集
列表,但我只想依赖于可见行为)。
我不会尝试修改任何内容。 />
我希望你回答我的问题并回顾我的结论。
代码在最后,连同como和gcc的输出。
此代码仅在C99模式下编译。

1.很明显,对于某些大型临时数据,编译器有时必须保留一些内存。关于临时值的存储,标准是什么意思?


很少。但6.5.2.2p5说:


" ...如果试图修改函数调用的结果或

后访问它在下一个序列点,行为是未定义的。


这意味着这个临时存储。没有必要超越

的下一个序列点。这意味着指向它的指针变为

在下一个序列点之后不确定。

是否定义了(C& V),未定义或未指定?


这意味着它可以被访问到下一个序列点。

C从不说明如何分配内存,未定义行为的概念

等与特定代码和构造有关,而不是分配技术。

标准对我程序的输出有何评价?


在调用printf()之前,有一个关键点是在调用它之前只是

。所以你传递的指针的值是不确定的,因为行为是未定义的。

2.表达式是`f()。a [0] ''有效吗?
函数调用(或产生右值的任何其他运算符)的结果的值被访问,但是没有序列点,所以似乎没有该区域的显式UB。如果指针(f()。a + 0)具有无效值(6.5.3.2p4),OTOH是未定义的行为。即使由于某种原因它是有效的并且没有对象,那么如果lvalue`f()。a [0]''在<时没有指定对象,则它是未定义的行为评估(6.3.2.1p1)。无论如何,似乎答案取决于对于右边界的临时物是否是一个物体。


6.3.2.1p3肯定表明f()。f()。a [0]的一部分评估为

a指向第一个元素的指针一个数组对象。

3.如果是sfunc_static()(下面),临时
的地址可能与静态对象相同,因为修改结果
一个fn呼叫提高了UB,因此没有什么可以保护。


第一个问题是它们是否必须是

抽象机器中的不同对象。这并不完全清楚,但我们假设是的。然后如果

调用者有办法测试临时对象的地址

对静态对象的地址那么他们就必须是

不平等。然而,正如所写的那样似乎是不可能的,所以你可以将它们视为同一个对象。如果静态对象具有外部

链接,则它们需要不同,或者至少表现得像它们一样。

4.类似的参数适用于=运算符(地址val可以与s1的地址相同)。 (条件和逗号运算符在gcc输出中重用操作数对象存储的值。)


其他非左值结构的来源不太清楚,如6.5.2.2p5

并不适用于他们。还不太清楚这个临时对象

必须与抽象机器中的s1不同。

5. Const对象存储总是可以作为其<的存储重用br /> value,因为如果该对象被修改则为UB。
I''m examining the existence of temporary objects by looking at
their addresses. The trick is to create a structure that contains
an array as its first member. In an expression the array rvalue
is converted to a pointer to its first member. Since this address
is also the address of the array, and that is the address of the
structure, I conclude that this is also the address of the temporary
storage for the structure (r)value.

I''m aware of "Heisenberg effect", ie. in absence of an observer
(".a" operator) the actual behaviour of the operand expressions
might be different. Some behaviours are impossible to measure,
eg. in expression `x = f()'' it''s impossible to check if `f()''
returns directly into `x'', or into a temporary (or other) object,
which is then copied into `x'' (I could of course analyze the assembly
listing, but I want to rely only on visible behaviour).
I don''t attempt to modify anything.

I would like you to answer my questions and review my conclusions.
The code is at the end, together with the output for como and gcc.
This code compiles only in C99 mode.

1. It is obvious that for some large temporary data a compiler
must sometimes reserve some memory. What does the Standard
say about storage for temporary values?
Very little. However 6.5.2.2p5 says:

"... If an attempt is made to modify the result of a function call or to
access it after the next sequence point, the behavior is undefined."

Which means that this "temporary storage" doesn''t have to last beyond the
next sequence point. That implies that a pointer to it becomes
indeterminate after the next sequence point.
Is it defined (C&V), undefined or unspecified?
The implication is that it can be accessed up to the next sequence point.
C never says how memory is allocated, the concepts of undefined behaviour
etc. relate to specific code and constructs not allocation techniques.
What does the Standard say about
the output from my program?
There is a squence point after the evaluation of printf()''s argumets just
before it is called. So the value of the pointer you pass is indeterminate
within printf() so the behaviour is undefined.
2. Is the expression `f().a[0]'' valid? Value of the result of
function call (or any other operator that yields an rvalue) is
accessed, but there''s no sequence point, so there doesn''t seem to
be an explicit UB in that area. OTOH it is undefined behaviour if
the pointer (f().a + 0) has invalid value (6.5.3.2p4). Even if for
some reason it is valid and there''s no object, then it is undefined
behaviour if the lvalue `f().a[0]'' does not designate an object when
evaluated (6.3.2.1p1). Anyway, it seems like the answer depends
on whether the temporary thingy for the rvalue is an object or not.
6.3.2.1p3 certainly suggests that the f().a part of f().a[0] evaluates to
a pointer to the first element of an array object.
3. In case of sfunc_static() (below) the address of the temporary
could be the same as the static object, because modifying the result
of a fn call raises UB, therefore there is nothing to "protect".
The first question is whether they have to be distinct objects in the
abstract machine. That isn''t entirely clear but lets assume yes. Then if
the caller had a way of testing the address of the temporary object
against the address of the static object then they would have to be
unequal. However as written that doesn''t seem to be possible so you''re
right they could be the same object. If the static object had external
linkage they would need to be different, or at least behave as if they are.
4. Similar argument applies to "=" operator (address "val" could
be the same as that of "s1"). (Conditional and comma operators
in gcc output reuse the operand object storage for the value.)
Other sources of non-lvalue structs are much less clear as 6.5.2.2p5
doesn''t apply to them. It is also less clear that this temporary object
has to be different to s1 in the abstract machine.
5. Const object storage can always be reused as storage for its
value, because it is UB if that object is modified.




仍然存在测试const对象地址的问题

兑换临时物品的地址。


....


劳伦斯



There is still the issue of testing the address of the const object
against the address of the temporary object.

....

Lawrence

Lawrence Kirby写道:
Lawrence Kirby wrote:
2005年7月21日星期四09:30:04 +0000,S.Tobias写道:
On Thu, 21 Jul 2005 09:30:04 +0000, S.Tobias wrote:
我''通过查看他们的地址来检查临时物体的存在。诀窍是创建一个包含数组作为其第一个成员的结构。


< snip>

2.表达式`f()。a [0]'有效吗?
函数调用(或产生右值的任何其他运算符)的结果的值被访问,但是没有序列点,所以似乎没有该区域的显式UB。如果指针(f()。a + 0)具有无效值(6.5.3.2p4),OTOH是未定义的行为。即使由于某种原因它是有效的并且没有对象,那么如果lvalue`f()。a [0]''在<时没有指定对象,则它是未定义的行为评估(6.3.2.1p1)。无论如何,似乎答案取决于是否rvalue的临时性是否是一个对象。
I''m examining the existence of temporary objects by looking at
their addresses. The trick is to create a structure that contains
an array as its first member.
<snip>
2. Is the expression `f().a[0]'' valid? Value of the result of
function call (or any other operator that yields an rvalue) is
accessed, but there''s no sequence point, so there doesn''t seem to
be an explicit UB in that area. OTOH it is undefined behaviour if
the pointer (f().a + 0) has invalid value (6.5.3.2p4). Even if for
some reason it is valid and there''s no object, then it is undefined
behaviour if the lvalue `f().a[0]'' does not designate an object when
evaluated (6.3.2.1p1). Anyway, it seems like the answer depends
on whether the temporary thingy for the rvalue is an object or not.



我同意。最初我误解了它,并在我开始的线程中断言

昨天6.8.6.4#3意味着回报不是一个对象,但

实际上它意味着相反:


6.8.6.4#3表示将值转换为对象当

表达式类型与返回类型不同时,暗示

当类型相同时。


所以函数必须返回一个临时对象,该对象至少存在于下一个序列点的



6.3.2.1p3当然表明f().f的一部分( ).a [0]计算指向数组对象的第一个元素的指针。


I agree. Initially I misread it and asserted in the thread I started
yesterday that 6.8.6.4#3 implies that the return isn''t an object, but
actually it implies the opposite:

6.8.6.4#3 states that "the value is converted ... to an object" when
the expression type is different to the return type, and by implication
when the type is the same.

So a function must return a temporary object that exists at least until
the next sequence point.
6.3.2.1p3 certainly suggests that the f().a part of f().a[0] evaluates to
a pointer to the first element of an array object.

3.如果是sfunc_static()(下面)的地址,临时
可能与静态对象相同,因为修改fn调用的结果会引发UB,因此没有什么可以保护。
第一个问题是他们是否有在抽象机器中成为不同的对象。这并不完全清楚,但我们假设是。
3. In case of sfunc_static() (below) the address of the temporary
could be the same as the static object, because modifying the result
of a fn call raises UB, therefore there is nothing to "protect".
The first question is whether they have to be distinct objects in the
abstract machine. That isn''t entirely clear but lets assume yes.




同意,目前尚不清楚。我看不出有充分的理由假设是的但是

(除了概念清晰度) - 在什么情况下它会有用

对象地址进行不同的比较?

那么如果调用者有办法测试临时对象的地址
对静态对象的地址那么他们必须是不等的。然而,正如所写似乎不可能


以下内容有什么问题(又一次,在什么情况下可能会这样?b $ b这样一个测试是否有用?):


sfunc_static_obj.a == sfunc_static()。a

所以你是对的,他们可能是同一个对象。


< snip>

4.类似的论据适用于= operator(地址val可以



Agreed, it isn''t clear. I can''t see a good reason to assume yes though
(apart from conceptual clarity) - in what situation would it be useful
for the object addresses to compare differently?
Then if
the caller had a way of testing the address of the temporary object
against the address of the static object then they would have to be
unequal. However as written that doesn''t seem to be possible
What''s wrong with the following (and again, in what situation might
such a test be useful?):

sfunc_static_obj.a == sfunc_static().a
so you''re
right they could be the same object.
<snip>
4. Similar argument applies to "=" operator (address "val" could

与s1相同)。 (条件和逗号运算符在gcc输出中重用操作数对象存储的值。)
be the same as that of "s1"). (Conditional and comma operators
in gcc output reuse the operand object storage for the value.)



非左值结构的其他来源不太清楚,如6.5.2.2p5
并不适用于他们。还不太清楚这个临时对象必须与抽象机器中的s1不同。



Other sources of non-lvalue structs are much less clear as 6.5.2.2p5
doesn''t apply to them. It is also less clear that this temporary object
has to be different to s1 in the abstract machine.

5. Const对象存储总是可以作为其<的存储重用br /> value,因为如果该对象被修改则为UB。
5. Const object storage can always be reused as storage for its
value, because it is UB if that object is modified.



仍然存在针对临时地址测试const对象的地址的问题对象。



There is still the issue of testing the address of the const object
against the address of the temporary object.




我在上述情况下会问同样的问题 - 什么时候会是

重要的是对象不同?



I''d ask the same question in these cases as above - when would it be
important that the objects be different?


Lawrence Kirby< lk **** @ netactive.co.uk>写道:
Lawrence Kirby <lk****@netactive.co.uk> wrote:
2005年7月21日星期四09:30:04 +0000,S.Tobias写道:
On Thu, 21 Jul 2005 09:30:04 +0000, S.Tobias wrote:
1很明显,对于某些大型临时数据,编译器有时必须保留一些内存。标准对于临时值的存储说了什么?
1. It is obvious that for some large temporary data a compiler
must sometimes reserve some memory. What does the Standard
say about storage for temporary values?



非常少。但是6.5.2.2p5说:

" ...如果尝试修改函数调用的结果或在下一个序列点之后访问它,行为是undefined。

这意味着这个临时存储。没有必要超越
下一个序列点。这意味着指向它的指针在下一个序列点之后变得不确定。



Very little. However 6.5.2.2p5 says:

"... If an attempt is made to modify the result of a function call or to
access it after the next sequence point, the behavior is undefined."

Which means that this "temporary storage" doesn''t have to last beyond the
next sequence point. That implies that a pointer to it becomes
indeterminate after the next sequence point.

是否定义了(C& V),未定义或未指定?
Is it defined (C&V), undefined or unspecified?



这意味着它可以被访问到下一个序列点。



The implication is that it can be accessed up to the next sequence point.




我同意它有点暗示函数返回(和其他

rvalues:"?:",",")可能是可修改的,但它还没有

a(强)保证有一个对象(它说是关于

一个_attempt_来修改右值,它并不意味着rvalues

可以被修改或者可以指定对象)。

C从不说明如何分配内存,未定义行为的概念等等与特定代码相关,构造不是分配技术。



I agree it sort of suggests that the function return (and other
rvalues as well: "?:", ",") may "modifiable", but it isn''t yet
a (strong) guarantee that there is an object (it says about
an _attempt_ to modify an rvalue, it doesn''t mean yet that rvalues
may be modified or may designate objects at all).
C never says how memory is allocated, the concepts of undefined behaviour
etc. relate to specific code and constructs not allocation techniques.



我的意思是表达式的语义是否为

定义/未定义/未指定,n行为(虽然它最终会影响它的价值)。



What I meant is whether the semantics for the expressions were
defined/undefined/unspecified, not behaviour (although it affects
it in the end as well).

标准对于什么说了什么?我的程序的输出是什么?
What does the Standard say about
the output from my program?



在调用printf()之前只有
之后有一个响应点。因此,你传递的指针的值在printf()中是不确定的,所以行为是未定义的。



There is a squence point after the evaluation of printf()''s argumets just
before it is called. So the value of the pointer you pass is indeterminate
within printf() so the behaviour is undefined.




我同意(如果我们可以谈论的话)一个右值对象 - 见下文。


但这可以通过两种方式轻松修复:


#define PRINT(msg,ptr)printf ("%s:\ t%lld \ n",msg,(long long)(void *)(ptr))

^^^^^^^^^^^

然后行为是部分实现定义,我们可能会询问打印值,或者至少是否标准保证

他们到相等(对于我程序中打印的对)。


或者我可以修改程序并测试这样的表达式:

sa ==(0, s).a

,问题是标准对其结果有什么保证?。


(我不会改变,现在发布我的程序的新版本,但我会记住上面的内容。要有一个正常工作的版本,让我们的屁股ume打印

宏被更改。)



I agree (if at all we can talk about an rvalue object - see below).

But this is easily fixed in two ways:

#define PRINT(msg, ptr) printf("%s: \t%lld\n", msg, (long long)(void*)(ptr))
^^^^^^^^^^^
and then the behaviour is partly implementation defined, and we may
ask about the printed values, or at least whether the Standard guarantees
them to be equal (for the pairs printed in my program).

Or I might modify the program and test expressions like this:
s.a == (0,s).a
and the question is "What does the Standard guarantee about its result?".

(I won''t change and post a new version of my program now, but I''ll
have above in mind. To have a working version, let''s assume PRINT
macro was changed.)

2.表达式是`f()。a [0]' '有效吗?
函数调用(或产生右值的任何其他运算符)的结果的值被访问,但是没有序列点,所以似乎没有该区域的显式UB。如果指针(f()。a + 0)具有无效值(6.5.3.2p4),OTOH是未定义的行为。即使由于某种原因它是有效的并且没有对象,那么如果lvalue`f()。a [0]''在<时没有指定对象,则它是未定义的行为评估(6.3.2.1p1)。无论如何,似乎答案取决于是否rvalue的临时性是否是一个对象。
2. Is the expression `f().a[0]'' valid? Value of the result of
function call (or any other operator that yields an rvalue) is
accessed, but there''s no sequence point, so there doesn''t seem to
be an explicit UB in that area. OTOH it is undefined behaviour if
the pointer (f().a + 0) has invalid value (6.5.3.2p4). Even if for
some reason it is valid and there''s no object, then it is undefined
behaviour if the lvalue `f().a[0]'' does not designate an object when
evaluated (6.3.2.1p1). Anyway, it seems like the answer depends
on whether the temporary thingy for the rvalue is an object or not.



6.3.2.1p3肯定建议f()。 f()的一部分.a [0]计算指向数组对象的第一个元素的指针。



6.3.2.1p3 certainly suggests that the f().a part of f().a[0] evaluates to
a pointer to the first element of an array object.




现在我不是确定有一个对象(存储)(在抽象的

机器中)。标准应该_first_表明那里有一个保证的

对象。我认为该条款也可以理解为:由于没有

存储,`f()。a''被转换为指向任何

的指针宾语;或者:由于没有存储,因此未定义`f()。a''

被转换并因此调用UB;实际上并没有说每个数组表达式都有相应的对象。


6.2.4定义了三种存储并定义了何时存在保留。

[给别人注意:n869.txt与

之间的标准在该部分有重大变化。]

所有点数这个条款有一个共同点:它们描述了

标识符的声明。在标准存储的其他位置

是为未命名的对象定义的(例如复合文字)。无处可以

我发现一个描述可能适合讨论的临时性事物。

我的一些其他想法(不一定与什么一致

我上面已经写过):


6.2.4p2:

#[...]
$ b $时指针的值变得不确定b#它指向的对象到达其生命周期的末尾。

这大致意味着:对象,指针,无对象,指针变为

不确定。既然/如果从来没有任何基础对象

为rvalue表达式,则值'f()。a''不一定是

不确定(但问题是转换的内容仍然存在)。

(相同的逻辑:void * p =(void *)1234;)


假设:

struct s {int a [2]; int m; }

^^^

如果存在基础对象(对于右值),这个表达式是否有效意味着



((struct s)(void *)(0,s).a) - > m;

上面我规避了操作数对&的约束。 "必须

是左值,即。这是错误的:

(&(0,s)) - > m; // CV

虽然,如果它是正确的,它将意味着完全相同的事情。

(IOW:如果struct rvalue包含一个数组,则意味着

整个struct rvalue必须有一个相应的对象。)


即使6.3.2.1p3暗示必须创建一些存储空间,

它仅表示其初始元素;它并不严格意味着必须为其他元素保留存储空间。同时:

f()。a [0];

可能没问题,这可能不是:

f()。a [1] ;


-

Stan Tobias

mailx`echo si *** @FamOuS.BedBuG.pAlS.INVA LID | sed s / [[:upper:]] // g`



Now I''m not sure there is an object (storage) at all (in the abstract
machine). The Standard should _first_ state that there is a guaranteed
object there. I think that clause maybe also read as: Since there is no
storage, `f().a'' is converted to a pointer which does not point to any
object; or: Since there is no storage, it is undefined to what `f().a''
is converted and thus invokes UB; it doesn''t actually say there that
every array expression has a corresponding object.

6.2.4 defines three kinds of storage and defines when it is reserved.
[Note to others: There are significant changes between n869.txt and
the Standard in that part.]
All points of this clause have one thing in common: they describe
declarations of identifiers. In other places of the Standard storage
is defined for unnamed objects (eg. compound literals). Nowhere could
I find a description that could fit temporary thingies under discussion.
Some other thoughts of mine (not necessarily consistent with what
I have written above):

6.2.4p2:
# [...] The value of a pointer becomes indeterminate when
# the object it points to reaches the end of its lifetime.
This roughly means: "object, pointer, no-object, pointer becomes
indeterminate". Since/if there has never been any underlying object
for rvalue expression, the value `f().a'' need not be necessarily
indeterminate (but the problem to what it is converted remains).
(Same logic for: void *p = (void*)1234; )

Suppose:
struct s { int a[2]; int m; }
^^^
If there is an underlying object (for the rvalue), would it mean
that this expression is valid?
( (struct s)(void*)(0,s).a )->m;
Above I circumvented the constraint that the operand for "&" must
be an lvalue, ie. this would be wrong:
(&(0,s))->m; //CV
although, if it were right, it would mean exactly the same thing.
(IOW: If a struct rvalue contains an array, it means that
the whole struct rvalue must have a corresponding object.)

Even if 6.3.2.1p3 is to imply that some storage has to be created,
it says only about its "initial element"; it doesn''t strictly
imply that storage has to be reserved for other elements. While:
f().a[0];
might be fine, this might not be:
f().a[1];

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`


这篇关于储存临时工的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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