Any comments on the correctness of the statements 1, 2a, 2b, 3 and 4 in
the code below?
If they are correct, then the definition of an object as well as that of
an lvalue is broken in C99 by the following reasoning:
foo() does not return an object, so the return of foo() conceptually is
not stored, yet we are able to obtain a pointer to one of its member
elements, therefore it must be stored, therefore foo() does return an
object, which is a contradiction.
6.5.2.2#5 prevents us from storing and later using foo().ar anyhow, but
C99 seems to be confused about whether conceptually a function returns
something that is stored (Stan Tobias's concept of a temporary variable)
or is just a value.
Both gcc and como online compile this code in strict C99 mode, and both
fault in C90 mode. Como online accepts foo().ar as an isolated statement
but not as an argument to printf.
#include <stdio.h>
struct s {char ar[3];} foo(void)
{
struct s s = {"ab"};
return s;
}
int main (void)
{
/* 1. C90/C99 prohibit this because foo()'s return is not an
* object - 6.8.6.4#3 refers to "the value of the function call"
* rather than "the object returned by the function call". However
* by C99's broken definition it is unintentedly an lvalue */
/* &foo(); */
/* 2a. By C90 foo().ar is not an lvalue so we can't take its
* address.
* 2b. By C99's broken definition it is an lvalue but not an
* object. 6.5.2.3#1 specifically allows foo().ar and
* 6.5.2.3#3 confirms that it is an lvalue */
/* &foo().ar; */
/* 3. By C99, ar decays to char* because of a wording change in
* 6.3.2.1#3 from "lvalue that has type" to "expression that has
* type" so this is valid */
foo().ar;
/* 4. As for (3) */
&foo().ar[0];
/* With gcc in C99 mode this compiles, runs and prints the
* 2 ptrs */
printf("%p\n", (void *)&foo().ar[0]);
printf("%p\n", (void *)foo().ar);
return 0;
} 9 2025
On Tue, 19 Jul 2005 23:25:27 GMT, Netocrat <ne******@dodo. com.au>
wrote in comp.lang.c: Any comments on the correctness of the statements 1, 2a, 2b, 3 and 4 in the code below?
If they are correct, then the definition of an object as well as that of an lvalue is broken in C99 by the following reasoning:
That the definition of lvalue is broken in C99 is an acknowledged
fact. But the proper place to discuss this is really comp.std.c, not
here.
foo() does not return an object, so the return of foo() conceptually is not stored, yet we are able to obtain a pointer to one of its member elements, therefore it must be stored, therefore foo() does return an object, which is a contradiction.
6.5.2.2#5 prevents us from storing and later using foo().ar anyhow, but C99 seems to be confused about whether conceptually a function returns something that is stored (Stan Tobias's concept of a temporary variable) or is just a value.
Both gcc and como online compile this code in strict C99 mode, and both fault in C90 mode. Como online accepts foo().ar as an isolated statement but not as an argument to printf.
#include <stdio.h> struct s {char ar[3];} foo(void) { struct s s = {"ab"}; return s; }
int main (void) { /* 1. C90/C99 prohibit this because foo()'s return is not an * object - 6.8.6.4#3 refers to "the value of the function call" * rather than "the object returned by the function call". However * by C99's broken definition it is unintentedly an lvalue */ /* &foo(); */ /* 2a. By C90 foo().ar is not an lvalue so we can't take its * address. * 2b. By C99's broken definition it is an lvalue but not an * object. 6.5.2.3#1 specifically allows foo().ar and * 6.5.2.3#3 confirms that it is an lvalue */ /* &foo().ar; */ /* 3. By C99, ar decays to char* because of a wording change in * 6.3.2.1#3 from "lvalue that has type" to "expression that has * type" so this is valid */ foo().ar; /* 4. As for (3) */ &foo().ar[0]; /* With gcc in C99 mode this compiles, runs and prints the * 2 ptrs */ printf("%p\n", (void *)&foo().ar[0]); printf("%p\n", (void *)foo().ar);
return 0; }
You are missing the (admittedly non-normative) section on undefined
behavior in Annex J. Specifically:
"— An attempt is made to modify the result of a function call, a
conditional operator, an assignment operator, or a comma operator, or
to access it after the next sequence point (6.5.2.2, 6.5.15, 6.5.16,
6.5.17)."
So your &foo().ar is quite legal, but attempting to use it later by
retaining the pointer produces undefined behavior. Which
implementations are not required to diagnose. In fact, there is
nothing in the standard that requires this to be a valid pointer. It
could be a null pointer, or a random value in a pointer.
There have already been threads on this in comp.std.c, Google the
group.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jack Klein wrote: [T]he proper place to discuss this is really comp.std.c, not here.
You are right. My judgement was out and the post was OT.
You are missing the (admittedly non-normative) section on undefined behavior in Annex J. Specifically:
"- An attempt is made to modify the result of a function call, a conditional operator, an assignment operator, or a comma operator, or to access it after the next sequence point (6.5.2.2, 6.5.15, 6.5.16, 6.5.17)."
Actually my reference to "6.5.2.2#5 prevent[ing] us from storing and
later using foo().ar anyhow" was an attempt to include that part of the
standard.
There have already been threads on this in comp.std.c, Google the group.
I must overcome my tendency to post before searching.
On Tue, 19 Jul 2005 23:25:27 +0000, Netocrat wrote: Any comments on the correctness of the statements 1, 2a, 2b, 3 and 4 in the code below?
If they are correct, then the definition of an object as well as that of an lvalue is broken in C99 by the following reasoning:
foo() does not return an object, so the return of foo() conceptually is not stored, yet we are able to obtain a pointer to one of its member elements, therefore it must be stored, therefore foo() does return an object, which is a contradiction.
There is clearly a temporary object in the execution environment. See
below.
6.5.2.2#5 prevents us from storing and later using foo().ar anyhow, but C99 seems to be confused about whether conceptually a function returns something that is stored (Stan Tobias's concept of a temporary variable) or is just a value.
Both gcc and como online compile this code in strict C99 mode, and both fault in C90 mode. Como online accepts foo().ar as an isolated statement but not as an argument to printf.
#include <stdio.h> struct s {char ar[3];} foo(void) { struct s s = {"ab"}; return s; }
int main (void) { /* 1. C90/C99 prohibit this because foo()'s return is not an * object - 6.8.6.4#3 refers to "the value of the function call" * rather than "the object returned by the function call". However * by C99's broken definition it is unintentedly an lvalue */
Where does the standard say that the return value of a function is an
lvalue? The only sensible way to read the definition of lvalue in
6.3.2.1p1 is to say that it specifies the meaning of the term when it is
used in the standard, it is *not* a statement of when an expression is to
be considered an lvalue.
/* &foo(); */ /* 2a. By C90 foo().ar is not an lvalue so we can't take its * address. * 2b. By C99's broken definition it is an lvalue but not an * object.
lvalues exist in the translation environment, objects at in the
execution environment. Since we're tlking about the translation
environment it cannot be an object. However an lvalue in the translation
environment can designate an object in the execution environment.
From above. The standard never talks about the result of an operator being
"an object" even if the result is an lvalue. It is important to
distinguish these 2 concepts. The presence of an lvalue (and the absence
of undefined behaviour) implies the existence of an object at runtime. In
the case of foo().ar[0] the creation of an lvalue is deferred but when it
does come into being it implies the existence of an object at runtime.
6.5.2.3#1 specifically allows foo().ar and * 6.5.2.3#3 confirms that it is an lvalue */
The . operator doesn't require its left hand operand to be an lvalue. If
it isn't the result isn't either. That is the case here i.e. no lvalue is
involved.
/* &foo().ar; */ /* 3. By C99, ar decays to char* because of a wording change in * 6.3.2.1#3 from "lvalue that has type" to "expression that has * type" so this is valid */
& requires its operand to be an lvalue or function designator (or some
other things not relevant here); this is a constraint violation.
foo().ar; /* 4. As for (3) */ &foo().ar[0];
This is different because the [] operator creates an lvalue, and is also
one of the "other things" specified as the operand of &.
/* With gcc in C99 mode this compiles, runs and prints the * 2 ptrs */ printf("%p\n", (void *)&foo().ar[0]); printf("%p\n", (void *)foo().ar);
Those have undefined behaviour in C99 so gcc is at liberty to print the 2
pointers if it wants to.
return 0; }
Lawrence
On Thu, 21 Jul 2005 12:10:21 +0100, Lawrence Kirby wrote: On Tue, 19 Jul 2005 23:25:27 +0000, Netocrat wrote:
<snip> #include <stdio.h> struct s {char ar[3];} foo(void) { struct s s = {"ab"}; return s; }
int main (void) { /* 1. C90/C99 prohibit this because foo()'s return is not an * object - 6.8.6.4#3 refers to "the value of the function call" * rather than "the object returned by the function call". However * by C99's broken definition it is unintentedly an lvalue */
Where does the standard say that the return value of a function is an lvalue?
The standard does not anywhere explicitly specify that a function is,
or is not, an lvalue.
The only sensible way to read the definition of lvalue in 6.3.2.1p1 is to say that it specifies the meaning of the term when it is used in the standard,
That may be sensible, but it leaves the lvalue-ness of some expressions
undefined. I compiled a list of all the cases specifically mentioned
by the standard:
lvalues:
6.5.1#2 an identifier declared as designating an object
6.5.1#4 a string literal
6.5.1#5 a parenthesized expr if the unparenthezised expr is an lvalue
6.5.2.3#3 struct expression members accessed with "." if the struct
expression is an lvalue
6.5.2.3#4 struct expression members accessed with "->"
6.5.2.5#5 a compound literal
6.5.3.2#4 the result of "*" if the operand points to an object
7.5#2 errno
non-lvalues:
6.5.3.2#3 the result of "&*"
6.5.16#3 an assignment expression
Non-normative footnotes: cast, comma and conditional expressions
Amongst others, this list is missing function returns.
So I used the reasoning apparently supported by Pete, Tim Rentsch, and
Michael Mair in the recent thread "gcc: pointer to array": that since
it is italicized, 6.3.2.1#1 contains the sole definition of an lvalue
(I think it's reasonable to add "unless an expression's lvalue-ness is
otherwise specified elsewhere in a normative part of the standard").
Given that the lvalue-ness of function returns and constants is not
elsewhere defined, they match the definition of 6.3.2.1#1 - worse, they
match the definition of "modifiable lvalue".
it is *not* a statement of when an expression is to be considered an lvalue.
How would you construct such a statement in reference to the standard,
or do you agree that the inability to do so in all cases is one reason
that the C99 lvalue definition is broken? /* &foo(); */ /* 2a. By C90 foo().ar is not an lvalue so we can't take its * address. * 2b. By C99's broken definition it is an lvalue but not an * object.
lvalues exist in the translation environment, objects at in the execution environment. Since we're tlking about the translation environment it cannot be an object. However an lvalue in the translation environment can designate an object in the execution environment.
From above. The standard never talks about the result of an operator being "an object" even if the result is an lvalue. It is important to distinguish these 2 concepts. The presence of an lvalue (and the absence of undefined behaviour) implies the existence of an object at runtime. In the case of foo().ar[0] the creation of an lvalue is deferred but when it does come into being it implies the existence of an object at runtime.
How then do you respond to my original claim that the wording of
6.8.6.4#3 implies the opposite?
<snip>
the [] operator creates an lvalue
How would you support that statement using the standard?
Given that you do not accept a function return as an lvalue in C99 and
interpret that an array index always results in an lvalue, I accept the
rest of your reasoning with one query: /* With gcc in C99 mode this compiles, runs and prints the * 2 ptrs */ printf("%p\n", (void *)&foo().ar[0]); printf("%p\n", (void *)foo().ar);
Those have undefined behaviour in C99 so gcc is at liberty to print the 2 pointers if it wants to.
What makes the first printf undefined?
Finally, if you agree with Jack Klein that this is off-topic, please
cross-post and set the follow-up to comp.std.c. It seems borderline
and I am no longer sure either way.
Netocrat wrote: On Thu, 21 Jul 2005 12:10:21 +0100, Lawrence Kirby wrote: On Tue, 19 Jul 2005 23:25:27 +0000, Netocrat wrote:
<snip> /* With gcc in C99 mode this compiles, runs and prints the * 2 ptrs */ printf("%p\n", (void *)&foo().ar[0]); printf("%p\n", (void *)foo().ar);
Those have undefined behaviour in C99 so gcc is at liberty to print the 2 pointers if it wants to.
What makes the first printf undefined?
I'll answer my own question: accessing the result of foo() after the
next sequence point.
Netocrat wrote: I compiled a list of all the cases specifically mentioned by the standard:
lvalues: 6.5.1#2 an identifier declared as designating an object 6.5.1#4 a string literal 6.5.1#5 a parenthesized expr if the unparenthezised expr is an lvalue 6.5.2.3#3 struct expression members accessed with "." if the struct expression is an lvalue 6.5.2.3#4 struct expression members accessed with "->" 6.5.2.5#5 a compound literal 6.5.3.2#4 the result of "*" if the operand points to an object
What if the operand is a null pointer or an indeterminate pointer?
7.5#2 errno
--
pete
pete wrote: Netocrat wrote:
I compiled a list of all the cases specifically mentioned by the standard:
lvalues: 6.5.1#2 an identifier declared as designating an object 6.5.1#4 a string literal 6.5.1#5 a parenthesized expr if the unparenthezised expr is an lvalue 6.5.2.3#3 struct expression members accessed with "." if the struct expression is an lvalue 6.5.2.3#4 struct expression members accessed with "->" 6.5.2.5#5 a compound literal 6.5.3.2#4 the result of "*" if the operand points to an object
What if the operand is a null pointer or an indeterminate pointer?
Then it obviously doesn't point to an object, and 6.5.3.2#4 says
nothing about the lvalue-ness of the result. By your reasoning as I
understand it, in this case "the" definition of 6.3.2.1#1 must be
considered, by which we still classify the result as an lvalue.
By both 6.5.3.2#4 and 6.3.2.1#1 the behavior is undefined. 7.5#2 errno
"Netocrat" <ne******@dodo. com.au> writes: [snip]
So I used the reasoning apparently supported by Pete, Tim Rentsch, and Michael Mair in the recent thread "gcc: pointer to array": that since it is italicized, 6.3.2.1#1 contains the sole definition of an lvalue (I think it's reasonable to add "unless an expression's lvalue-ness is otherwise specified elsewhere in a normative part of the standard").
I feel obliged to jump in and say something here, since apparently I'm
at least partly responsible for the confusion.
What the standard *means* in 6.3.2.1 is something like "an lvalue is
something that has the property that ..., and whether or not something
is an lvalue is defined in other places in the standard." That isn't
what it *says*, but that's what it means.
I'm one of the people who believes that the C standard document should
say what it means and mean what it says, and when it doesn't then that
should be pointed out. Other people have different ideas, such as "it
should have only one sensible interpretation" , which I don't really
disagree with, except that saying what it means and meaning what it
says should be a pre-requisite, since otherwise whether there is only
one sensible interpretation (not to mention what the interpretation
is) seems too dependent on who is doing the interpreting.
For these reasons I responded to the discussion about the definition
of lvalue. Probably I should have posted that to comp.std.c; but,
I'm usually reluctant to change newsgroups mid-thread since I'm never
sure who read which newsgroup.
Meanwhile, back in *this* newsgroup, an lvalue should be understood to
mean only those expressional forms that are identified as lvalues in
sections 6.5.x (and probably 6.7.something, but I'm not going to look
up the reference). The definition in 6.3.2.1 should be read not as a
definition but merely as a remark about what sorts of things are in
the realm of the term "lvalue".
And, in case any committee members are listening, please clean up the
language in 6.3.2.1#1 to make it clear that the normative text that
defines whether or not some particular thing is an lvalue is given in
the various sections relating to expressions, etc. Similar deferrals
of defining properties are done in other places in the standard (eg
6.2.7#1 for compatible type); the definition of lvalue deserves no
less.
Netocrat wrote: pete wrote: Netocrat wrote:
I compiled a list of all the cases specifically mentioned by the standard:
lvalues: 6.5.1#2 an identifier declared as designating an object 6.5.1#4 a string literal 6.5.1#5 a parenthesized expr if the unparenthezised expr is an lvalue 6.5.2.3#3 struct expression members accessed with "." if the struct expression is an lvalue 6.5.2.3#4 struct expression members accessed with "->" 6.5.2.5#5 a compound literal 6.5.3.2#4 the result of "*" if the operand points to an object What if the operand is a null pointer or an indeterminate pointer?
Then it obviously doesn't point to an object, and 6.5.3.2#4 says nothing about the lvalue-ness of the result. By your reasoning as I understand it, in this case "the" definition of 6.3.2.1#1 must be considered, by which we still classify the result as an lvalue.
That makes it easier for your compiler to tell you
if you don't have an lvalue where you need one.
By both 6.5.3.2#4 and 6.3.2.1#1 the behavior is undefined.
--
pete This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Steve Lamb |
last post by:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Ok, this one I did try before coming here... :)
I am trying to report the status of what is going on to the status
bar of the main window of my wxPython app. I know I'm on the right
track with SetStatusText() but it doesn't always alter the text. What
the program is doing is taking a filename and passing it through two
different external programs. One of them is taking a little bit of...
|
by: Krzysztof Stachlewski |
last post by:
I tried to run the following piece of code:
Python 2.3.4 (#53, May 25 2004, 21:17:02) on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> o = object()
>>> o.a = 5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'object' object has no attribute 'a'
|
by: Daniel |
last post by:
Hello =)
I have an object which contains a method that should execute every x ms. I
can use setInterval inside the object construct like this -
self.setInterval('ObjectName.methodName()', this.pinginterval);
- but is there no way to do this without using the literal ObjectName? If I
write 'this.methodName()' I get "Line 1 Char 1: Object doesn't support this
property or method." in IE, and nothing happens in Firebird.
|
by: FredC |
last post by:
OS Name Microsoft Windows XP Professional
Version 5.1.2600 Service Pack 2 Build 2600
Total Physical Memory 1,024.00 MB
MDE 2003 Version 7.1.3008
..NET Framework 1.1 Version 1.1.4322 SP1
Microsoft Visual C# .NET 69462-335-0000007-18707
Crystal Reports for Visual Studio .NET AAP50-GS0000S-WCK00C3
|
by: Kurt Van Campenhout |
last post by:
Hi,
I am trying to get/set Terminal server information in the active directory
on a windows 2000 domain. Since the ADSI calls for TS don't work until W2K3,
I need to do it myself.
I'm fairly new to VB.NET, so I need some help.
Here is a code snippit :
| |
by: Kiyomi |
last post by:
Hello,
I am trying to replace my alert message box with a popup page.
In my page behind,
|
by: XML newbie: Urgent pls help! |
last post by:
I am using VB.Net. My program is to connect to a remote IPAddress. Once, it
verifies the login information it should display the SessionID and enable
some button . I appreciate your help and thanku in advance
When I run the pgm , I get the error:
Can't parse login information. Object Reference not set to an instance of an
object. I have added the Try-catch in all my functions. In ParseLoginResponse
function, it catches the above...
|
by: FAQ server |
last post by:
-----------------------------------------------------------------------
FAQ Topic - I have window.status="Moomin"; why doesn't the statusbar change?
-----------------------------------------------------------------------
When changing the status in an event (e.g. onmouseover) you
should return true from the event. Also a number of browsers
require a short delay before setting the status to overcome their
default behaviour with the...
|
by: nmm32 |
last post by:
I am trying to use Ajax with JSP to populate a 2nd drop down list based on the chosen option of the first one. I am getting the error "Object Expected" on the line 13-14 of the HTML:
<script language="javascript">
// Global Variable for XmlHttp Request Object
var xmlhttp;
var yearDDL;
function handleOnChangepType(ddl)
{
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |