Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.std.c > #1734 > unrolled thread
| Started by | Keith Thompson <kst-u@mib.org> |
|---|---|
| First post | 2012-12-07 18:34 -0800 |
| Last post | 2013-01-20 15:36 -0500 |
| Articles | 20 — 6 participants |
Back to article view | Back to comp.std.c
Description of "." operator Keith Thompson <kst-u@mib.org> - 2012-12-07 18:34 -0800
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2012-12-08 10:43 -0800
Re: Description of "." operator Jens Gustedt <jens.gustedt@loria.fr> - 2012-12-10 00:35 +0100
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2012-12-09 20:02 -0800
Re: Description of "." operator jgk@panix.com (Joe keane) - 2012-12-09 23:34 +0000
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2012-12-09 20:00 -0800
Re: Description of "." operator Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-20 23:32 -0800
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2012-12-21 02:08 -0800
Re: Description of "." operator Eric Sosman <esosman@comcast-dot-net.invalid> - 2012-12-21 09:18 -0500
Re: Description of "." operator Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-21 08:45 -0800
Re: Description of "." operator Tim Rentsch <txr@alumni.caltech.edu> - 2012-12-21 08:37 -0800
Re: Description of "." operator Shao Miller <sha0.miller@gmail.com> - 2013-01-06 01:23 -0500
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2013-01-05 23:51 -0800
Re: Description of "." operator Shao Miller <sha0.miller@gmail.com> - 2013-01-06 13:49 -0500
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2013-01-06 22:12 -0800
Re: Description of "." operator Shao Miller <sha0.miller@gmail.com> - 2013-01-17 23:19 -0500
Re: Description of "." operator Shao Miller <sha0.miller@gmail.com> - 2013-01-18 20:47 -0500
Re: Description of "." operator Keith Thompson <kst-u@mib.org> - 2013-01-18 20:14 -0800
Re: Description of "." operator jgk@panix.com (Joe keane) - 2013-01-20 20:07 +0000
Re: Description of "." operator Shao Miller <sha0.miller@gmail.com> - 2013-01-20 15:36 -0500
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-12-07 18:34 -0800 |
| Subject | Description of "." operator |
| Message-ID | <lntxrxnufa.fsf@nuthaus.mib.org> |
N1570 6.5.2.3p3 says:
A postfix expression followed by the . operator and an identifier
designates a member of a structure or union object. The value
is that of the named member, and is an lvalue if the first
expression is an lvalue.
Consider the use of the word "object" in the first sentence.
An expression of struct type doesn't necessarily refer to an *object* of
that type. For example:
struct pair { int x; int y; };
struct pair func(void) {
struct pair result = { 10, 20 };
return result;
}
...
int y = func().y;
And the second quoted sentence seems to explictly acknowledge that the
left operand needn't refer to an object.
Shouln't the phrase "a member of a structure or union object" be "a
member of a structure or union *value*"?
If not, in the example code above, what object is being referred to?
("result" no longer exists after the function returns.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-12-08 10:43 -0800 |
| Message-ID | <lnpq2ko04x.fsf@nuthaus.mib.org> |
| In reply to | #1734 |
Keith Thompson <kst-u@mib.org> writes:
> N1570 6.5.2.3p3 says:
>
> A postfix expression followed by the . operator and an identifier
> designates a member of a structure or union object. The value
> is that of the named member, and is an lvalue if the first
> expression is an lvalue.
>
> Consider the use of the word "object" in the first sentence.
>
> An expression of struct type doesn't necessarily refer to an *object* of
> that type. For example:
>
> struct pair { int x; int y; };
> struct pair func(void) {
> struct pair result = { 10, 20 };
> return result;
> }
> ...
> int y = func().y;
>
> And the second quoted sentence seems to explictly acknowledge that the
> left operand needn't refer to an object.
>
> Shouldn't the phrase "a member of a structure or union object" be "a
> member of a structure or union *value*"?
Or, perhaps better, "a member of a structure or union *expression*".
> If not, in the example code above, what object is being referred to?
> ("result" no longer exists after the function returns.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Jens Gustedt <jens.gustedt@loria.fr> |
|---|---|
| Date | 2012-12-10 00:35 +0100 |
| Message-ID | <50C5202E.3060604@loria.fr> |
| In reply to | #1735 |
Am 08.12.2012 19:43, schrieb Keith Thompson: > Keith Thompson <kst-u@mib.org> writes: >> N1570 6.5.2.3p3 says: >> >> A postfix expression followed by the . operator and an identifier >> designates a member of a structure or union object. The value >> is that of the named member, and is an lvalue if the first >> expression is an lvalue. >> >> Consider the use of the word "object" in the first sentence. >> >> ... >> >> Shouldn't the phrase "a member of a structure or union object" be "a >> member of a structure or union *value*"? > > Or, perhaps better, "a member of a structure or union *expression*". I'd go for: a member of an expression with structure or union type (In your example there would have been an object if your struct also would have included an array type) Jens
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-12-09 20:02 -0800 |
| Message-ID | <lnvccamu68.fsf@nuthaus.mib.org> |
| In reply to | #1737 |
Jens Gustedt <jens.gustedt@loria.fr> writes:
> Am 08.12.2012 19:43, schrieb Keith Thompson:
>> Keith Thompson <kst-u@mib.org> writes:
>>> N1570 6.5.2.3p3 says:
>>>
>>> A postfix expression followed by the . operator and an identifier
>>> designates a member of a structure or union object. The value
>>> is that of the named member, and is an lvalue if the first
>>> expression is an lvalue.
>>>
>>> Consider the use of the word "object" in the first sentence.
>>>
>>> ...
>>>
>>> Shouldn't the phrase "a member of a structure or union object" be "a
>>> member of a structure or union *value*"?
>>
>> Or, perhaps better, "a member of a structure or union *expression*".
>
> I'd go for:
>
> a member of an expression with structure or union type
I think both phrases mean the same thing, but I do like yours better.
> (In your example there would have been an object if your struct also
> would have included an array type)
Yes (as of C2011).
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | jgk@panix.com (Joe keane) |
|---|---|
| Date | 2012-12-09 23:34 +0000 |
| Message-ID | <ka375e$es6$1@reader1.panix.com> |
| In reply to | #1734 |
In article <lntxrxnufa.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote:
>N1570 6.5.2.3p3 says:
>
> A postfix expression followed by the . operator and an identifier
> designates a member of a structure or union object. The value
> is that of the named member, and is an lvalue if the first
> expression is an lvalue.
>
>Consider the use of the word "object" in the first sentence.
>
>An expression of struct type doesn't necessarily refer to an *object* of
>that type.
Look up 'temporary lifetime' (6.2.4).
>For example:
>
> struct pair { int x; int y; };
> struct pair func(void) {
> struct pair result = { 10, 20 };
> return result;
> }
> ...
> int y = func().y;
Change your code to:
struct pair { int x; int y; char thisisbs[1]; };
struct pair func(void) {
struct pair result = { 10, 20 };
return result;
}
...
int y = func().y;
to make it work.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-12-09 20:00 -0800 |
| Message-ID | <lnzk1mmu8c.fsf@nuthaus.mib.org> |
| In reply to | #1736 |
jgk@panix.com (Joe keane) writes:
> In article <lntxrxnufa.fsf@nuthaus.mib.org>,
> Keith Thompson <kst-u@mib.org> wrote:
>>N1570 6.5.2.3p3 says:
>>
>> A postfix expression followed by the . operator and an identifier
>> designates a member of a structure or union object. The value
>> is that of the named member, and is an lvalue if the first
>> expression is an lvalue.
>>
>>Consider the use of the word "object" in the first sentence.
>>
>>An expression of struct type doesn't necessarily refer to an *object* of
>>that type.
>
> Look up 'temporary lifetime' (6.2.4).
I'm quite familiar with it. It's irrelevant to my example; it applies
only to a struct or union that contains a member of array type.
>>For example:
>>
>> struct pair { int x; int y; };
>> struct pair func(void) {
>> struct pair result = { 10, 20 };
>> return result;
>> }
>> ...
>> int y = func().y;
>
> Change your code to:
>
> struct pair { int x; int y; char thisisbs[1]; };
> struct pair func(void) {
> struct pair result = { 10, 20 };
> return result;
> }
> ...
> int y = func().y;
>
> to make it work.
I wasn't asking how to make the code work -- and it already works
just fine. A strict reading of the wording of the standard might
imply that the code has undefined behavior, but that clearly (IMHO)
was not the intent. It's the wording of the standard that needs
fixing, not my code.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-12-20 23:32 -0800 |
| Message-ID | <kfn623v97x5.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #1734 |
Keith Thompson <kst-u@mib.org> writes:
> N1570 6.5.2.3p3 says:
>
> A postfix expression followed by the . operator and an identifier
> designates a member of a structure or union object. The value
> is that of the named member, and is an lvalue if the first
> expression is an lvalue.
>
> Consider the use of the word "object" in the first sentence.
>
> An expression of struct type doesn't necessarily refer to an *object* of
> that type. For example:
>
> struct pair { int x; int y; };
> struct pair func(void) {
> struct pair result = { 10, 20 };
> return result;
> }
> ...
> int y = func().y;
>
> And the second quoted sentence seems to explictly acknowledge that the
> left operand needn't refer to an object.
>
> Shouln't the phrase "a member of a structure or union object" be "a
> member of a structure or union *value*"?
>
> If not, in the example code above, what object is being referred to?
> ("result" no longer exists after the function returns.)
I agree the point should be addressed, but I think the problem is
more fundamental than just this operator. Consider the very
definition of the types, eg,
A /structure type/ describes a sequentially allocated nonempty
set of member objects, ...
Kind of implies that struct's exist only as objects, doesn't it?
A better solution, I think, is for all expressions with struct or
union type, or at least those that aren't produced directly from
lvalue conversion, be objects with temporary lifetime in the same
way that ones with array members are. Surely that corresponds to
the behavior (at least abstractly) that most people expect, eg,
with struct-returning functions -- right? And of course this
wouldn't have to result in storage being reserved during actual
execution, because of the abstract machine principles and the
as if rule, so what's the downside? ISTM the end result would
be smaller, simpler, and more consistent than what there is now.
Am I missing something?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-12-21 02:08 -0800 |
| Message-ID | <lnpq23pvj5.fsf@nuthaus.mib.org> |
| In reply to | #1778 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
> Keith Thompson <kst-u@mib.org> writes:
>
>> N1570 6.5.2.3p3 says:
>>
>> A postfix expression followed by the . operator and an identifier
>> designates a member of a structure or union object. The value
>> is that of the named member, and is an lvalue if the first
>> expression is an lvalue.
>>
>> Consider the use of the word "object" in the first sentence.
>>
>> An expression of struct type doesn't necessarily refer to an *object* of
>> that type. For example:
>>
>> struct pair { int x; int y; };
>> struct pair func(void) {
>> struct pair result = { 10, 20 };
>> return result;
>> }
>> ...
>> int y = func().y;
>>
>> And the second quoted sentence seems to explictly acknowledge that the
>> left operand needn't refer to an object.
>>
>> Shouln't the phrase "a member of a structure or union object" be "a
>> member of a structure or union *value*"?
>>
>> If not, in the example code above, what object is being referred to?
>> ("result" no longer exists after the function returns.)
>
> I agree the point should be addressed, but I think the problem is
> more fundamental than just this operator. Consider the very
> definition of the types, eg,
>
> A /structure type/ describes a sequentially allocated nonempty
> set of member objects, ...
>
> Kind of implies that struct's exist only as objects, doesn't it?
>
> A better solution, I think, is for all expressions with struct or
> union type, or at least those that aren't produced directly from
> lvalue conversion, be objects with temporary lifetime in the same
> way that ones with array members are. Surely that corresponds to
> the behavior (at least abstractly) that most people expect, eg,
> with struct-returning functions -- right? And of course this
> wouldn't have to result in storage being reserved during actual
> execution, because of the abstract machine principles and the
> as if rule, so what's the downside? ISTM the end result would
> be smaller, simpler, and more consistent than what there is now.
> Am I missing something?
That's one way to approach it; the only way to have a struct value would
be for it to be the value of some object.
But I'd prefer to recognize that struct values can exist even in the
absence of any object.
Structs can be passed as function arguments, returned as function
results, and assigned, very much like scalars. This function:
int answer(void) { return 42; }
doesn't create an object of type int; why then should this function:
struct foo func(void) { struct foo result; return result; }
create a struct foo object that exists after the function has
returned?
On the other hand, compound literals are specified to refer to
anonymous objects rather than just yielding values, so I suspect
the committee would agree with you more than with me.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2012-12-21 09:18 -0500 |
| Message-ID | <kb1r3i$48g$1@dont-email.me> |
| In reply to | #1785 |
On 12/21/2012 5:08 AM, Keith Thompson wrote:
>[...]
> That's one way to approach it; the only way to have a struct value would
> be for it to be the value of some object.
If the expression is not evaluated (think `sizeof'), the `.'
operator works just fine even if there's no struct object or
struct value anywhere in sight.
struct {
int foo, bar;
} *ptr = NULL;
size_t size = sizeof (*ptr).bar;
--
Eric Sosman
esosman@comcast-dot-net.invalid
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-12-21 08:45 -0800 |
| Message-ID | <kfn7gob73r4.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #1786 |
Eric Sosman <esosman@comcast-dot-net.invalid> writes:
> On 12/21/2012 5:08 AM, Keith Thompson wrote:
>>[...]
>> That's one way to approach it; the only way to have a struct value would
>> be for it to be the value of some object.
>
> If the expression is not evaluated (think `sizeof'), the `.'
> operator works just fine even if there's no struct object or
> struct value anywhere in sight.
>
> struct {
> int foo, bar;
> } *ptr = NULL;
> size_t size = sizeof (*ptr).bar;
I don't see the relevance. The result of sizeof depends only
on the type of its operand. Naturally there are no values or
objects involved, for structs or anything else (not counting
an operand of VLA type). How does this bear on the discussion
of the thread?
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-12-21 08:37 -0800 |
| Message-ID | <kfnbodn744c.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #1785 |
Keith Thompson <kst-u@mib.org> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
>> Keith Thompson <kst-u@mib.org> writes:
>>
>>> N1570 6.5.2.3p3 says:
>>>
>>> A postfix expression followed by the . operator and an identifier
>>> designates a member of a structure or union object. The value
>>> is that of the named member, and is an lvalue if the first
>>> expression is an lvalue.
>>>
>>> Consider the use of the word "object" in the first sentence.
>>>
>>> An expression of struct type doesn't necessarily refer to an *object* of
>>> that type. For example:
>>>
>>> struct pair { int x; int y; };
>>> struct pair func(void) {
>>> struct pair result = { 10, 20 };
>>> return result;
>>> }
>>> ...
>>> int y = func().y;
>>>
>>> And the second quoted sentence seems to explictly acknowledge that the
>>> left operand needn't refer to an object.
>>>
>>> Shouln't the phrase "a member of a structure or union object" be "a
>>> member of a structure or union *value*"?
>>>
>>> If not, in the example code above, what object is being referred to?
>>> ("result" no longer exists after the function returns.)
>>
>> I agree the point should be addressed, but I think the problem is
>> more fundamental than just this operator. Consider the very
>> definition of the types, eg,
>>
>> A /structure type/ describes a sequentially allocated nonempty
>> set of member objects, ...
>>
>> Kind of implies that struct's exist only as objects, doesn't it?
>>
>> A better solution, I think, is for all expressions with struct or
>> union type, or at least those that aren't produced directly from
>> lvalue conversion, be objects with temporary lifetime in the same
>> way that ones with array members are. Surely that corresponds to
>> the behavior (at least abstractly) that most people expect, eg,
>> with struct-returning functions -- right? And of course this
>> wouldn't have to result in storage being reserved during actual
>> execution, because of the abstract machine principles and the
>> as if rule, so what's the downside? ISTM the end result would
>> be smaller, simpler, and more consistent than what there is now.
>> Am I missing something?
>
> That's one way to approach it; the only way to have a struct value would
> be for it to be the value of some object.
>
> But I'd prefer to recognize that struct values can exist even in the
> absence of any object.
>
> Structs can be passed as function arguments, returned as function
> results, and assigned, very much like scalars. This function:
>
> int answer(void) { return 42; }
>
> doesn't create an object of type int;
There is a sense in which it does, because of how returning
values from a function works - in particular, assigning a
function return value is not subject to the "exact same object
or no overlap" rule for regular assignment. However, I take
your point.
> why then should this function:
>
> struct foo func(void) { struct foo result; return result; }
>
> create a struct foo object that exists after the function has
> returned?
In practice I expect it actually does, especially if the function
being called is defined in a different translatin unit. But of
course I mean to speak only of the abstract semantics, in which
case the point of (abstractly) creating a struct object is to
simplify the semantic descriptions needed. It just seems easier,
descriptionally speaking.
> On the other hand, compound literals are specified to refer to
> anonymous objects rather than just yielding values, so I suspect
> the committee would agree with you more than with me.
Oh, it's important for compound literals, because their address
can be taken, and that can be used (in most cases) after the next
sequence point. This condition doesn't hold for the ephemeral
"struct values" that need be present only until the end of the
current full expression (if that long, but in general they might
be needed up to the point that the current full expression
completes).
Having said that, I still think the "objects rather than values"
stance for (sub-)expressions having struct/union type would
simplify the semantic descriptions involved, and I hope people
would agree with it on that basis (or in the alternative point
out why that isn't so or a different viewpoint that is simpler).
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-06 01:23 -0500 |
| Message-ID | <kcb58h$s8g$1@dont-email.me> |
| In reply to | #1734 |
On 12/7/2012 21:34, Keith Thompson wrote:
> N1570 6.5.2.3p3 says:
>
> A postfix expression followed by the . operator and an identifier
> designates a member of a structure or union object. The value
> is that of the named member, and is an lvalue if the first
> expression is an lvalue.
>
> Consider the use of the word "object" in the first sentence.
>
3.1:
"1 access
〈execution-time action〉 to read or modify the value of an object
2 NOTE 1 Where only one of these two actions is meant, ‘‘read’’ or
‘‘modify’’ is used.
3 NOTE 2 ‘‘Modify’’ includes the case where the new value being
stored is the same as the previous value.
4 NOTE 3 Expressions that are not evaluated do not access objects."
3.15:
"1 object
region of data storage in the execution environment, the contents
of which can represent values
2 NOTE When referenced, an object may be interpreted as having a
particular type; see 6.3.2.1."
3.19:
"1 value
precise meaning of the contents of an object when interpreted as
having a specific type"
> An expression of struct type doesn't necessarily refer to an *object* of
> that type.
Why not? Is it because of:
- The possible lack of a definition for the lifetime[6.2.4]?
- The possible denial of accessing its stored value via an lvalue
expression[6.5p7]?
> For example:
>
> struct pair { int x; int y; };
> struct pair func(void) {
> struct pair result = { 10, 20 };
> return result;
> }
> ...
> int y = func().y;
>
6.5.2.2p5:
"If the expression that denotes the called function has type pointer
to function returning an object type, the function call expression has
the same type as that object type, and has the value determined as
specified in 6.8.6.4. Otherwise, the function call has type void."
6.8.6.4p3:
"If a return statement with an expression is executed, the value of
the expression is returned to the caller as the value of the function
call expression. If the expression has a type different from the return
type of the function in which it appears, the value is converted as if
by assignment to an object having the return type of the function.160)"
Could it still be a region of data storage in the execution environment?
> And the second quoted sentence seems to explictly acknowledge that the
> left operand needn't refer to an object.
>
I think one has to equate lvalue with object to draw that conclusion,
right? If an lvalue expression locates an object, could a non-lvalue
expression still be associated with a region of data storage, without
location concerns?
And p7 is pretty close to your example.
> Shouln't the phrase "a member of a structure or union object" be "a
> member of a structure or union *value*"?
>
Unless the intention is to actually define it to be an object, where
perhaps 6.2.4 and 6.5p7 and who knows where else need some adjustment.
> If not, in the example code above, what object is being referred to?
> ("result" no longer exists after the function returns.)
>
If "lvalue" is well-thought-of as "an object locator value," then
perhaps the answer is: An object we can't locate? Well wait a minute...
that's what you're asking... :)
It seems a bit similar to the case with 'register'-specified objects,
except that there are lvalue expressions possible with these latter;
neither apparently have programmer-accessible locations.
Interesting stuff!
- Shao Miller
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-05 23:51 -0800 |
| Message-ID | <lnmwwm4umo.fsf@nuthaus.mib.org> |
| In reply to | #1815 |
[Something strange happened to the non-ASCII characters in your article.
I haven't taken the time to fix them.]
Shao Miller <sha0.miller@gmail.com> writes:
> On 12/7/2012 21:34, Keith Thompson wrote:
>> N1570 6.5.2.3p3 says:
>>
>> A postfix expression followed by the . operator and an identifier
>> designates a member of a structure or union object. The value
>> is that of the named member, and is an lvalue if the first
>> expression is an lvalue.
>>
>> Consider the use of the word "object" in the first sentence.
>
> 3.1:
>
> "1 access
> 〈execution-time action〉 to read or modify the value of an object
> 2 NOTE 1 Where only one of these two actions is meant, ‘‘read’’ or
> ‘‘modify’’ is used.
> 3 NOTE 2 ‘‘Modify’’ includes the case where the new value being
> stored is the same as the previous value.
> 4 NOTE 3 Expressions that are not evaluated do not access objects."
>
> 3.15:
>
> "1 object
> region of data storage in the execution environment, the contents
> of which can represent values
> 2 NOTE When referenced, an object may be interpreted as having a
> particular type; see 6.3.2.1."
>
> 3.19:
>
> "1 value
> precise meaning of the contents of an object when interpreted as
> having a specific type"
Like too many of the standard's "definitions", that's incomplete. There
can be values that have nothing to do with the contents of an object.
>> An expression of struct type doesn't necessarily refer to an *object* of
>> that type.
>
> Why not? Is it because of:
>
> - The possible lack of a definition for the lifetime[6.2.4]?
> - The possible denial of accessing its stored value via an lvalue
> expression[6.5p7]?
Why should there be an object? The expression 42 is of an object type,
but it doesn't refer to any object
>> For example:
>>
>> struct pair { int x; int y; };
>> struct pair func(void) {
>> struct pair result = { 10, 20 };
>> return result;
>> }
>> ...
>> int y = func().y;
>>
>
> 6.5.2.2p5:
>
> "If the expression that denotes the called function has type pointer
> to function returning an object type, the function call expression has
> the same type as that object type, and has the value determined as
> specified in 6.8.6.4. Otherwise, the function call has type void."
>
> 6.8.6.4p3:
>
> "If a return statement with an expression is executed, the value of
> the expression is returned to the caller as the value of the function
> call expression. If the expression has a type different from the return
> type of the function in which it appears, the value is converted as if
> by assignment to an object having the return type of the function.160)"
That doesn't imply that there's an object. The value is converted *as
if by assignment to an object*, meaning simply that the conversion
follows the same rules followed by assignment to an object.
`return 42;` in a function returning double doesn't convert the int
value 42 to an object of type double; it merely converts it to a value
of type double. IMHO it should be the same for struct types as for
scalar types.
> Could it still be a region of data storage in the execution environment?
Evaluating `2 + 2` may well use some storage for the operands and/or the
result, but there's no object in the abstract machine, just values.
>> And the second quoted sentence seems to explictly acknowledge that the
>> left operand needn't refer to an object.
>>
>
> I think one has to equate lvalue with object to draw that conclusion,
> right? If an lvalue expression locates an object, could a non-lvalue
> expression still be associated with a region of data storage, without
> location concerns?
If it's associated with a region of data storage, i.e., with an object,
doesn't that mean that it designates an object? And if it designates an
object, it's an lvalue.
> And p7 is pretty close to your example.
>
>> Shouln't the phrase "a member of a structure or union object" be "a
>> member of a structure or union *value*"?
>
> Unless the intention is to actually define it to be an object, where
> perhaps 6.2.4 and 6.5p7 and who knows where else need some adjustment.
Perhaps, but the acknowedgement that the left operand needn't be an
lvalue argues otherwise, I think.
>> If not, in the example code above, what object is being referred to?
>> ("result" no longer exists after the function returns.)
>
> If "lvalue" is well-thought-of as "an object locator value," then
> perhaps the answer is: An object we can't locate? Well wait a minute...
> that's what you're asking... :)
And my answer is that *no* object is being referred to.
> It seems a bit similar to the case with 'register'-specified objects,
> except that there are lvalue expressions possible with these latter;
> neither apparently have programmer-accessible locations.
But register objects are still objects, and can clearly be referred to
by lvalues.
> Interesting stuff!
>
> - Shao Miller
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-06 13:49 -0500 |
| Message-ID | <kcch03$i71$1@dont-email.me> |
| In reply to | #1816 |
On 1/6/2013 02:51, Keith Thompson wrote:
> [Something strange happened to the non-ASCII characters in your article.
> I haven't taken the time to fix them.]
>
D'oh.
> Shao Miller <sha0.miller@gmail.com> writes:
>> On 12/7/2012 21:34, Keith Thompson wrote:
>>> N1570 6.5.2.3p3 says:
>>>
>>> A postfix expression followed by the . operator and an identifier
>>> designates a member of a structure or union object. The value
>>> is that of the named member, and is an lvalue if the first
>>> expression is an lvalue.
>>>
>>> Consider the use of the word "object" in the first sentence.
>>
>> 3.1:
>>
>> "1 access
>> <execution-time action> to read or modify the value of an object
>> 2 NOTE 1 Where only one of these two actions is meant, "read" or
>> "modify" is used.
>> 3 NOTE 2 "Modify" includes the case where the new value being
>> stored is the same as the previous value.
>> 4 NOTE 3 Expressions that are not evaluated do not access objects."
>>
>> 3.15:
>>
>> "1 object
>> region of data storage in the execution environment, the contents
>> of which can represent values
>> 2 NOTE When referenced, an object may be interpreted as having a
>> particular type; see 6.3.2.1."
>>
>> 3.19:
>>
>> "1 value
>> precise meaning of the contents of an object when interpreted as
>> having a specific type"
>
> Like too many of the standard's "definitions", that's incomplete. There
> can be values that have nothing to do with the contents of an object.
>
Actually, I took it to have emphasis on "meaning." So I agree with you,
values exist independently of objects.
>>> An expression of struct type doesn't necessarily refer to an *object* of
>>> that type.
>>
>> Why not? Is it because of:
>>
>> - The possible lack of a definition for the lifetime[6.2.4]?
>> - The possible denial of accessing its stored value via an lvalue
>> expression[6.5p7]?
>
> Why should there be an object? The expression 42 is of an object type,
> but it doesn't refer to any object
>
I don't know if there is or not, but it does boggle me a bit to imagine
that the values _must_ be out-of-band relative to the definition of
"object." But if we imagine for the sake of discussion that '42' does
have an associated object, do the two points above stand in the way of
that scenario?
>>> For example:
>>>
>>> struct pair { int x; int y; };
>>> struct pair func(void) {
>>> struct pair result = { 10, 20 };
>>> return result;
>>> }
>>> ...
>>> int y = func().y;
>>>
>>
>> 6.5.2.2p5:
>>
>> "If the expression that denotes the called function has type pointer
>> to function returning an object type, the function call expression has
>> the same type as that object type, and has the value determined as
>> specified in 6.8.6.4. Otherwise, the function call has type void."
>>
>> 6.8.6.4p3:
>>
>> "If a return statement with an expression is executed, the value of
>> the expression is returned to the caller as the value of the function
>> call expression. If the expression has a type different from the return
>> type of the function in which it appears, the value is converted as if
>> by assignment to an object having the return type of the function.160)"
>
> That doesn't imply that there's an object. The value is converted *as
> if by assignment to an object*, meaning simply that the conversion
> follows the same rules followed by assignment to an object.
>
Agreed. (No claim that there was.) But a tiny note for random readers:
It's only converted, as if by assignment, for the case of a different
type. (I'm sure you already know that.)
The pieces quoted were only offered for their relevance to the
situation, but not as a response to the very interesting consideration
that you've shared in this thread.
> `return 42;` in a function returning double doesn't convert the int
> value 42 to an object of type double; it merely converts it to a value
> of type double. IMHO it should be the same for struct types as for
> scalar types.
>
You must be emphasizing the "no object involved" bit, rather than the
"converted" bit, since we don't often convert non-scalar values.
>> Could it still be a region of data storage in the execution environment?
>
> Evaluating `2 + 2` may well use some storage for the operands and/or the
> result, but there's no object in the abstract machine, just values.
>
Does the Standard say that somewhere, or does that statement stem from a
lack of discussion about it in the Standard?
>>> And the second quoted sentence seems to explictly acknowledge that the
>>> left operand needn't refer to an object.
>>>
>>
>> I think one has to equate lvalue with object to draw that conclusion,
>> right? If an lvalue expression locates an object, could a non-lvalue
>> expression still be associated with a region of data storage, without
>> location concerns?
>
> If it's associated with a region of data storage, i.e., with an object,
> doesn't that mean that it designates an object? And if it designates an
> object, it's an lvalue.
>
6.3.2.1p1:
"An lvalue is an expression (with an object type other than void)
that potentially designates an object;64) ..."
So I don't it's 100% clear, unless it had said "any" instead of "an".
If
expression-with-object-type-other-than-void-that-potentially-designates-an-object
is a set, then lvalue could be a subset.
But I interpret it the same way you do, except that I use the
[non-normative] foot-note to put an emphasis on "locator value".
Given:
void ex1(void) {
int x;
x = 42;
}
It's possible to imagine '42' as being an object that the programmer
cannot "locate," but that is still accessed for its value. Then in:
void ex2(int y) {
int x;
x = y;
}
The "lvalue conversion"[6.3.2.1p2] happens to 'y', which is a similar
process to the previous example, except that we can certainly access
_the_same_ object again and again, because we have this "locator value".
"Locator value" makes me think of aliasing, easily repeatable access and
the qualifications[6.7.3] of the object, rather than a notion of "lvalue
== object". While "lvalue" _certainly_ requires an object, that we
don't see a requirement of a "value == object" in most places allows an
implementation some freedom:
void ex1(void) {
int x;
x = 42;
}
'42' _needn't_ be an object, as the value of 'x' could be set to zero,
then incremented 42 times. But when we see the sentence of your
original consideration waaay up above, we could imagine that to define
that a struct value _always_has_ an associated object; just possibly one
whose "location" isn't particularly meaningful.
>> And p7 is pretty close to your example.
>>
>>> Shouln't the phrase "a member of a structure or union object" be "a
>>> member of a structure or union *value*"?
>>
>> Unless the intention is to actually define it to be an object, where
>> perhaps 6.2.4 and 6.5p7 and who knows where else need some adjustment.
>
> Perhaps, but the acknowedgement that the left operand needn't be an
> lvalue argues otherwise, I think.
>
(Argued against above. However, I don't claim either interpretation is
absolutely right. I don't know.)
>>> If not, in the example code above, what object is being referred to?
>>> ("result" no longer exists after the function returns.)
>>
>> If "lvalue" is well-thought-of as "an object locator value," then
>> perhaps the answer is: An object we can't locate? Well wait a minute...
>> that's what you're asking... :)
>
> And my answer is that *no* object is being referred to.
>
>> It seems a bit similar to the case with 'register'-specified objects,
>> except that there are lvalue expressions possible with these latter;
>> neither apparently have programmer-accessible locations.
>
> But register objects are still objects, and can clearly be referred to
> by lvalues.
Here's another idea:
#include <stdarg.h>
#include <stdio.h>
typedef struct { int x; } s_foo;
void ex3(int n, ...) {
va_list ap;
va_start(ap, n);
printf("%d\n", va_arg(ap, s_foo).x);
va_end(ap);
}
int main(void) {
s_foo foo = { 42 };
ex3(0, foo);
return 0;
}
I don't think 'va_arg' yields an lvalue, but if:
"A postfix expression followed by the . operator and an identifier
designates a member of a structure or union object. ..."
should be taken to mean that there definitely _is_ an object involved,
then I'd still wonder about its lifetime[6.2.4] and how we are able to
access its value without an lvalue[6.5p7].
- Shao Miller
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-06 22:12 -0800 |
| Message-ID | <ln4nitttce.fsf@nuthaus.mib.org> |
| In reply to | #1817 |
Shao Miller <sha0.miller@gmail.com> writes:
> On 1/6/2013 02:51, Keith Thompson wrote:
[...]
>> Shao Miller <sha0.miller@gmail.com> writes:
>>> On 12/7/2012 21:34, Keith Thompson wrote:
[...]
>>> 3.19:
>>>
>>> "1 value
>>> precise meaning of the contents of an object when interpreted as
>>> having a specific type"
>>
>> Like too many of the standard's "definitions", that's incomplete. There
>> can be values that have nothing to do with the contents of an object.
>>
>
> Actually, I took it to have emphasis on "meaning." So I agree with you,
> values exist independently of objects.
Right -- and that should apply to struct types as well as to scalar
types. At least, I can't think of any good reason why it shouldn't.
>>>> An expression of struct type doesn't necessarily refer to an *object* of
>>>> that type.
>>>
>>> Why not? Is it because of:
>>>
>>> - The possible lack of a definition for the lifetime[6.2.4]?
>>> - The possible denial of accessing its stored value via an lvalue
>>> expression[6.5p7]?
>>
>> Why should there be an object? The expression 42 is of an object type,
>> but it doesn't refer to any object
>
> I don't know if there is or not, but it does boggle me a bit to imagine
> that the values _must_ be out-of-band relative to the definition of
> "object." But if we imagine for the sake of discussion that '42' does
> have an associated object, do the two points above stand in the way of
> that scenario?
If we imagine that the constant `42` must have an associated object,
then I think we're talking about something other than C. I don't know
what meaningful conclusions can be drawn from such an assumption.
[...]
>> `return 42;` in a function returning double doesn't convert the int
>> value 42 to an object of type double; it merely converts it to a value
>> of type double. IMHO it should be the same for struct types as for
>> scalar types.
>
> You must be emphasizing the "no object involved" bit, rather than the
> "converted" bit, since we don't often convert non-scalar values.
Actually I don't think we *ever* convert non-scalar values, except
perhaps for a handful of special cases ((void)whatever, and the
implicit conversion of array and function expressions to pointers).
>>> Could it still be a region of data storage in the execution environment?
>>
>> Evaluating `2 + 2` may well use some storage for the operands and/or the
>> result, but there's no object in the abstract machine, just values.
>
> Does the Standard say that somewhere, or does that statement stem from a
> lack of discussion about it in the Standard?
Lack of discussion.
>>>> And the second quoted sentence seems to explictly acknowledge that the
>>>> left operand needn't refer to an object.
>>>
>>> I think one has to equate lvalue with object to draw that conclusion,
>>> right? If an lvalue expression locates an object, could a non-lvalue
>>> expression still be associated with a region of data storage, without
>>> location concerns?
>>
>> If it's associated with a region of data storage, i.e., with an object,
>> doesn't that mean that it designates an object? And if it designates an
>> object, it's an lvalue.
>
> 6.3.2.1p1:
>
> "An lvalue is an expression (with an object type other than void)
> that potentially designates an object;64) ..."
>
> So I don't it's 100% clear, unless it had said "any" instead of "an".
> If
> expression-with-object-type-other-than-void-that-potentially-designates-an-object
> is a set, then lvalue could be a subset.
I'm assuming that the definition of lvalue is exhaustive -- which IMHO
it certainly *should* be, but given the standard's track record perhaps
that's overly optimistic.
> But I interpret it the same way you do, except that I use the
> [non-normative] foot-note to put an emphasis on "locator value".
>
> Given:
>
> void ex1(void) {
> int x;
> x = 42;
> }
>
> It's possible to imagine '42' as being an object that the programmer
> cannot "locate," but that is still accessed for its value. Then in:
Sure, you can imagine that, but it hardly seems necessary or useful.
A function implementation may be stored in a region of memory, but that
doesn't make it an object. The implementation of malloc() and free()
probably stores metadata in memory, but I wouldn't call those C objects
either (if, for example, the standard library is implemented in
something other than C).
[...]
> void ex1(void) {
> int x;
> x = 42;
> }
>
> '42' _needn't_ be an object, as the value of 'x' could be set to zero,
> then incremented 42 times. But when we see the sentence of your
> original consideration waaay up above, we could imagine that to define
> that a struct value _always_has_ an associated object; just possibly one
> whose "location" isn't particularly meaningful.
A value of a struct type that happens to be sizeof (int) bytes can
be constructed without needing an "object" as easily as an int value
can be. A larger struct value is more likely to require a chunk of
memory to build it, but there shouldn't be a fundamental difference
based on the size. The "object", if any, isn't accessible (as an
object) to the program, and I argue that it *isn't* an object as
far as the abstract machine is concerned.
[...]
> I don't think 'va_arg' yields an lvalue, but if:
>
> "A postfix expression followed by the . operator and an identifier
> designates a member of a structure or union object. ..."
>
> should be taken to mean that there definitely _is_ an object involved,
> then I'd still wonder about its lifetime[6.2.4] and how we are able to
> access its value without an lvalue[6.5p7].
Arrays values don't work properly without having objects associated
with them; see C11's introduction of "temporary storage duration".
I don't think structs have the same issues.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-17 23:19 -0500 |
| Message-ID | <kdaih9$lui$1@dont-email.me> |
| In reply to | #1823 |
On 1/7/2013 01:12, Keith Thompson wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>> On 1/6/2013 02:51, Keith Thompson wrote:
> [...]
>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>> On 12/7/2012 21:34, Keith Thompson wrote:
> [...]
>>>> 3.19:
>>>>
>>>> "1 value
>>>> precise meaning of the contents of an object when interpreted as
>>>> having a specific type"
>>>
>>> Like too many of the standard's "definitions", that's incomplete. There
>>> can be values that have nothing to do with the contents of an object.
>>>
>>
>> Actually, I took it to have emphasis on "meaning." So I agree with you,
>> values exist independently of objects.
>
> Right -- and that should apply to struct types as well as to scalar
> types. At least, I can't think of any good reason why it shouldn't.
>
And unions too:
#include <stddef.h>
#include <stdio.h>
struct A {
int i;
int j;
};
struct B {
char ca[sizeof (int)];
int k;
};
union C {
struct A a;
struct B b;
};
int main(void) {
union C c1, c2;
if (offsetof(struct A, j) != offsetof(struct B, k))
return 0;
c1.a.j = 42;
/*
* Common initial sequence doesn't apply (no object)
* Effective type doesn't apply (no object)
* Type-punning applies
*/
printf("%d\n", (c2 = c1).b.k);
return 0;
}
Any problems, there?
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-18 20:47 -0500 |
| Message-ID | <kdcu00$cu3$1@dont-email.me> |
| In reply to | #1852 |
On 1/17/2013 23:19, Shao Miller wrote:
> On 1/7/2013 01:12, Keith Thompson wrote:
>> Shao Miller <sha0.miller@gmail.com> writes:
>>> On 1/6/2013 02:51, Keith Thompson wrote:
>> [...]
>>>> Shao Miller <sha0.miller@gmail.com> writes:
>>>>> On 12/7/2012 21:34, Keith Thompson wrote:
>> [...]
>>>>> 3.19:
>>>>>
>>>>> "1 value
>>>>> precise meaning of the contents of an object when
>>>>> interpreted as
>>>>> having a specific type"
>>>>
>>>> Like too many of the standard's "definitions", that's incomplete.
>>>> There
>>>> can be values that have nothing to do with the contents of an object.
>>>>
>>>
>>> Actually, I took it to have emphasis on "meaning." So I agree with you,
>>> values exist independently of objects.
>>
>> Right -- and that should apply to struct types as well as to scalar
>> types. At least, I can't think of any good reason why it shouldn't.
>>
>
> And unions too:
>
> #include <stddef.h>
> #include <stdio.h>
>
> struct A {
> int i;
> int j;
> };
>
> struct B {
> char ca[sizeof (int)];
Oops. I meant some scalar type with the same size as 'int', not an
array type. Oh well.
> int k;
> };
>
> union C {
> struct A a;
> struct B b;
> };
>
> int main(void) {
> union C c1, c2;
>
> if (offsetof(struct A, j) != offsetof(struct B, k))
> return 0;
>
> c1.a.j = 42;
>
> /*
> * Common initial sequence doesn't apply (no object)
> * Effective type doesn't apply (no object)
> * Type-punning applies
> */
> printf("%d\n", (c2 = c1).b.k);
>
> return 0;
> }
>
> Any problems, there?
>
Speaking of "temporary lifetime," I noticed that the following program
yielded the same pointer value, but I would've expected them to be
different:
#include <stdio.h>
int main(void) {
struct { char ca[6]; } foo;
printf("%p, ", (void *) foo.ca);
printf("%p\n", (void *) (foo = foo).ca);
return 0;
}
It seems to me that the array member of the rvalue should be different
than the array member of 'foo', since they're different objects; one is
'foo' and one is an object with temporary lifetime. Am I missing something?
gcc version 4.7.2 20120921 (Red Hat 4.7.2-2):
gcc -std=c11 -pedantic -Wall -Wextra -Werror -o rvalobj rvalobj.c
clang seems to give the expected results.
clang version 3.0 (tags/RELEASE_30/final):
clang -std=c1x -pedantic -Wall -Wextra -Werror -Wno-self-assign -o
rvalobj rvalobj.c
Maybe it's just a GCC bug, but I'm wondering if another interpretation
is possible.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2013-01-18 20:14 -0800 |
| Message-ID | <lnwqv995c4.fsf@nuthaus.mib.org> |
| In reply to | #1861 |
Shao Miller <sha0.miller@gmail.com> writes:
[...]
> Speaking of "temporary lifetime," I noticed that the following program
> yielded the same pointer value, but I would've expected them to be
> different:
>
> #include <stdio.h>
>
> int main(void) {
> struct { char ca[6]; } foo;
>
> printf("%p, ", (void *) foo.ca);
> printf("%p\n", (void *) (foo = foo).ca);
> return 0;
> }
That's interesting. For some reason, it hadn't occur to me that an
assignment, not just a function return, could create an object with
temporary lifetime.
> It seems to me that the array member of the rvalue should be different
> than the array member of 'foo', since they're different objects; one is
> 'foo' and one is an object with temporary lifetime. Am I missing something?
I think you're right.
> gcc version 4.7.2 20120921 (Red Hat 4.7.2-2):
>
> gcc -std=c11 -pedantic -Wall -Wextra -Werror -o rvalobj rvalobj.c
>
> clang seems to give the expected results.
>
> clang version 3.0 (tags/RELEASE_30/final):
>
> clang -std=c1x -pedantic -Wall -Wextra -Werror -Wno-self-assign -o
> rvalobj rvalobj.c
>
> Maybe it's just a GCC bug, but I'm wondering if another interpretation
> is possible.
Plenty of other interpretations are possible, but I agree with yours.
Another data point: gcc does the same thing with "-std=c99"; C99 didn't
have temporary lifetime. I'd argue that the program's behavior is
undefined by omission in C99, so "gcc -std=c99" can do anything it
likes. It looks like they didn't change it for "-std=c11".
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | jgk@panix.com (Joe keane) |
|---|---|
| Date | 2013-01-20 20:07 +0000 |
| Message-ID | <kdhipc$2ep$1@reader1.panix.com> |
| In reply to | #1861 |
In article <kdcu00$cu3$1@dont-email.me>,
Shao Miller <sha0.miller@gmail.com> wrote:
>Speaking of "temporary lifetime," I noticed that the following program
>yielded the same pointer value, but I would've expected them to be
>different:
>
>#include <stdio.h>
>
>int main(void) {
> struct { char ca[6]; } foo;
>
> printf("%p, ", (void *) foo.ca);
> printf("%p\n", (void *) (foo = foo).ca);
> return 0;
> }
I guess... the 'object' of the 'value' of an assignment expression is
the left-hand side?
% cat bar.c
#include <stdio.h>
#include <string.h>
struct bar
{
char a[5];
};
int main(int argc, char **argv)
{
struct bar x;
struct bar y;
struct bar *p;
int res;
memcpy((void *) &y, "FFFF", sizeof y);
p = &(x = y);
res = p == &x;
printf("%d\n", res);
return 0;
}
% diff bar.c bar2.cc
% gcc -o bar bar.c
bar.c: In function 'main':
bar.c:18: error: invalid lvalue in unary '&'
% g++ -o bar2 bar2.cc
% ./bar2
1
% cat barx.c
#include <stdio.h>
#include <string.h>
struct bar
{
char a[5];
};
int main(int argc, char **argv)
{
struct bar x;
struct bar y;
char *p;
int res;
memcpy((void *) &y, "FFFF", sizeof y);
p = &(x = y).a[0];
res = p == &x.a[0];
printf("%d\n", res);
return 0;
}
% diff barx.c barx2.cc
% gcc -o barx barx.c
% ./barx
1
% g++ -o barx2 barx2.cc
% ./barx2
1
This doesn't work with the function call example.
[toc] | [prev] | [next] | [standalone]
| From | Shao Miller <sha0.miller@gmail.com> |
|---|---|
| Date | 2013-01-20 15:36 -0500 |
| Message-ID | <kdhkg4$oa$1@dont-email.me> |
| In reply to | #1868 |
On 1/20/2013 15:07, Joe keane wrote:
> In article <kdcu00$cu3$1@dont-email.me>,
> Shao Miller <sha0.miller@gmail.com> wrote:
>> Speaking of "temporary lifetime," I noticed that the following program
>> yielded the same pointer value, but I would've expected them to be
>> different:
>>
>> #include <stdio.h>
>>
>> int main(void) {
>> struct { char ca[6]; } foo;
>>
>> printf("%p, ", (void *) foo.ca);
>> printf("%p\n", (void *) (foo = foo).ca);
>> return 0;
>> }
>
> I guess... the 'object' of the 'value' of an assignment expression is
> the left-hand side?
>
In which C? I would've said the "object" was one with temporary
lifetime, and is not the object designated by the LHS lvalue, in C11.
Of course, assignment and function calls aren't the only way to yield
rvalues. Another simple way is the comma operator. '(0, foo).ca'.
Conditional '?:' is another one.
> % cat bar.c
> #include <stdio.h>
> #include <string.h>
>
> struct bar
> {
> char a[5];
> };
>
>
> int main(int argc, char **argv)
> {
> struct bar x;
> struct bar y;
> struct bar *p;
> int res;
>
> memcpy((void *) &y, "FFFF", sizeof y);
> p = &(x = y);
> res = p == &x;
> printf("%d\n", res);
> return 0;
> }
> % diff bar.c bar2.cc
> % gcc -o bar bar.c
> bar.c: In function 'main':
> bar.c:18: error: invalid lvalue in unary '&'
> % g++ -o bar2 bar2.cc
> % ./bar2
> 1
> % cat barx.c
> #include <stdio.h>
> #include <string.h>
>
> struct bar
> {
> char a[5];
> };
>
>
> int main(int argc, char **argv)
> {
> struct bar x;
> struct bar y;
> char *p;
> int res;
>
> memcpy((void *) &y, "FFFF", sizeof y);
> p = &(x = y).a[0];
> res = p == &x.a[0];
> printf("%d\n", res);
> return 0;
> }
> % diff barx.c barx2.cc
> % gcc -o barx barx.c
> % ./barx
> 1
> % g++ -o barx2 barx2.cc
> % ./barx2
> 1
>
> This doesn't work with the function call example.
>
In C11? This doesn't work in C11, either. 'p' becomes indeterminate at
the semi-colon before the 'res' assignment, due to the temporary
lifetime of the object it had been assigned to point into.
--
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.
Cheerily," -- Richard Harter
[toc] | [prev] | [standalone]
Back to top | Article view | comp.std.c
csiph-web