473,663 Members | 2,738 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

The object status of function call returns

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;
}

Nov 15 '05 #1
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
Nov 15 '05 #2
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.

Nov 15 '05 #3
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

Nov 15 '05 #4
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.

Nov 15 '05 #5
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.

Nov 15 '05 #6
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
Nov 15 '05 #7
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


Nov 15 '05 #8
"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.
Nov 15 '05 #9
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
Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
4510
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...
2
1758
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'
28
20309
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.
2
1133
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
5
6531
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 :
4
2358
by: Kiyomi | last post by:
Hello, I am trying to replace my alert message box with a popup page. In my page behind,
0
1597
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...
3
4203
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...
1
8367
nmm32
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) {
0
8436
marktang
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...
0
8345
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,...
0
8634
tracyyun
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...
1
6186
isladogs
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...
0
5657
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();...
0
4182
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...
0
4349
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2763
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
2
2000
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.