473,441 Members | 1,955 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,441 software developers and data experts.

casts and lvalues

Continuing the discussion about casts, I would like to know
your opinions about the hairy subject of casts as lvalues, i.e.
int main(void)
{
long long a;
char *n;

(char *)a = n;
}
This will fail under lcc-win32, but MSVC and gcc will
accept it. I know that the standard prescribes the behavior
that lcc-win32 uses, but I left that behavior after a big
discussion about this several years ago. I had modified it,
and some people raised hell.

What are the problems of doing this? I mean not the usual
"the standard says so" but what problems would arise within the
language if this would be accepted?

Apparently gcc and msvc are still used, and this doesn't seem
to produce any big problems.

Thanks in advance for your comments, and I thank all people
that participated in the discussion yesterday.

jacob
Jun 24 '07
61 2740
Richard Heathfield wrote On 06/26/07 09:15,:
CBFalconer said:

>>Richard Heathfield wrote:

... snip ...
>>>Two problems with this - firstly, you're trying to nudge the
discussion further and further into the called function in an attempt
to shore up your case, but we're discussing the cast-expression, not
the execution details of the called function; and secondly, there
isn't necessarily a function call at all! The expression, remember,
was toupper((unsigned char)c), and the implementation is perfectly at
liberty to convert this into something like:
(((unsigned char)c) == EOF) ? EOF : __toupper[((unsigned char)c)]

where __toupper is an array in read-only memory.

No it can't. That expression evaluates c twice, and is forbidden
for macro expansions of the std. library (apart from getc).


Oops.

How about this:

((__zog = ((unsigned char)c)) == EOF) ? EOF :__toupper[__zog]
Oops again, I think. What is the sign of __zog?

More usually, you get something euivalent to

__toupper[(c) - EOF]

.... which is another incentive for EOF to be minus one
rather than, say, INT_MIN.

--
Er*********@sun.com
Jun 26 '07 #51
Eric Sosman wrote:
jacob navia wrote On 06/26/07 03:28,:
>Richard Heathfield wrote:
>>CBFalconer said:

Richard Heathfield wrote:

CBFalconer said:
>
>Richard Heathfield wrote:
<snip>

>>For example, there is
>>no lvalue in the (pointless but legal) statement:
>>>
>> toupper((unsigned char)c);
>Yes there is, although it is well hidden. The functional parameter.
No, it isn't well hidden. It isn't *there*. Not in that statement.
We must be missing each others points. Where do you think the
conversion of c goes?
It could easily go into a register, but that's beside the point. There's
no object in the statement I presented.

The result of the expression is stored in the stack.
(Or its equivalent for the mythical machines without
stack)

Nonsense. On the machine in front of me at this
very moment, the result goes into a CPU register (if
an actual function call is made). The chance that
*anything* gets pushed onto a stack is roughly one
in eight.
If within the called function the address of that parameter is taken
it must be stored in the stack.
Obviously the compiler can optimize it away, etc.

But if it lives in a register, it still is somewhere there.

In the same vein, if you say:

int c;

c = 56;

The fact that the integer "c" is stored in a register doesn't mean that
it is not a lvalue isn't it?

We have to separate conceptually stores that can be optimized away, and
details of compiler decisions that store the integer in a register or
whatever.

If I declare
int f;
f = 56;

There is an "f" object even if the compiler realizes that f is not used
anywhere in the function and optimizes the whole stuff away!

jacob
Jun 26 '07 #52
jacob navia wrote On 06/26/07 11:10,:
Eric Sosman wrote:
>>jacob navia wrote On 06/26/07 03:28,:
>>>Richard Heathfield wrote:
CBFalconer said:
>Richard Heathfield wrote:
>
>
>>CBFalconer said:
>>
>>
>>>Richard Heathfield wrote:

<snip>

>>>>For example, there is
>>>>no lvalue in the (pointless but legal) statement:
>>>>
>>>toupper((unsigned char)c);
>>>
>>>Yes there is, although it is well hidden. The functional parameter.
>>
>>No, it isn't well hidden. It isn't *there*. Not in that statement.
>
>We must be missing each others points. Where do you think the
>conversion of c goes?

It could easily go into a register, but that's beside the point. There's
no object in the statement I presented.

The result of the expression is stored in the stack.
(Or its equivalent for the mythical machines without
stack)

Nonsense. On the machine in front of me at this
very moment, the result goes into a CPU register (if
an actual function call is made). The chance that
*anything* gets pushed onto a stack is roughly one
in eight.

If within the called function the address of that parameter is taken
it must be stored in the stack.
Nonsense again. The CPU registers on the machine
in front of me at this moment are not addressable as
if they were RAM, but some machines' registers are.
Obviously the compiler can optimize it away, etc.

But if it lives in a register, it still is somewhere there.
Your exact words were "The result of the expression is
stored in the stack." I do not believe that "somewhere
there" is an adequate defense of that statement.

--
Er*********@sun.com
Jun 26 '07 #53
Richard Heathfield wrote, On 26/06/07 09:34:
jacob navia said:
>Keith Thompson wrote:
>>jacob navia <ja***@jacob.remcomp.frwrites:

<snip>
>>>The object exists, since we can even take its address
within the called function.
Yes, *within* the called function. The object (the parameter)
doesn't exist outside the function; it's a local object with
automatic storage duration.
Thanks. You agree with me then, that the object exists, and exists
before the call, even if it is not accessible.

No, he doesn't, and neither do I. As he rightly said, the object doesn't
exist until the function is called (if indeed a function *is* called
for the expression under consideration, which is not necessarily the
case). It's a local object with automatic storage duration, so it
doesn't exist until the function call actually happens.
>This is obvious if we read the standard 6.5.2.2 "Function calls",
where it is specified that after all assignments are done to the
function arguments there is a sequence point. At that sequence point
the arguments have been assigned but they are still not accessible
since the function call is not done yet.

Two problems with this - firstly, you're trying to nudge the discussion
further and further into the called function in an attempt to shore up
your case, but we're discussing the cast-expression, not the execution
details of the called function; and secondly, there isn't necessarily a
function call at all! The expression, remember, was toupper((unsigned
char)c), and the implementation is perfectly at liberty to convert this
into something like:
(((unsigned char)c) == EOF) ? EOF : __toupper[((unsigned char)c)]
No it isn't, since that evaluates c twice. It could, however, do:
__toupper[((unsigned char)c)+1]
and have EOF defined as -1.
where __toupper is an array in read-only memory.

*Now* where is your lvalue?
With my change to make it valid it is gone :-)
>Obviously the objects exist within the function call. They have a
constant address, and they retain their last assigned value.

Until the function (if there /is/ a function) returns, yes.
Indeed.
--
Flash Gordon
Jun 26 '07 #54
Richard Heathfield <rj*@see.sig.invalidwrites:
[...]
Oops.

How about this:

((__zog = ((unsigned char)c)) == EOF) ? EOF :__toupper[__zog]
How about a few more parentheses?

I'm too lazy to figure out what just this does for
toupper(toupper(c)), but it's not pretty.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #55
CBFalconer <cb********@yahoo.comwrites:
Richard Heathfield wrote:
>Keith Thompson said:

<snip>
>>An *argument* is not an object.

Hear, hear. So we are indeed in agreement after all, it seems.

Nonsense. An argument is always an expression, converted into an
object, which is not accessible before entry to the sub-routine.
At that point it can be treated as any other local object.
No, an argument is an expression whose value is *stored* in an object.
An argument and the corresponding parameter are two distinct things.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #56
jacob navia <ja***@jacob.remcomp.frwrites:
[...]
If within the called function the address of that parameter is taken
it must be stored in the stack.
Obviously the compiler can optimize it away, etc.

But if it lives in a register, it still is somewhere there.

In the same vein, if you say:

int c;

c = 56;

The fact that the integer "c" is stored in a register doesn't mean that
it is not a lvalue isn't it?
The object c is an object, not an lvalue.

The expression c on the left hand side of the assignment clearly is an
lvalue.
We have to separate conceptually stores that can be optimized away, and
details of compiler decisions that store the integer in a register or
whatever.

If I declare
int f;
f = 56;

There is an "f" object even if the compiler realizes that f is not used
anywhere in the function and optimizes the whole stuff away!
Of course f is an object.

Objects are not lvalues. Lvalues are not objects.
Arguments are not parameters. Parameters are not arguments.
Parameters are objects. Arguments are expressions, not objects.

What exactly are we arguing about here?

Let's take a simple example:

#include <stdio.h>
void func(int param)
{
printf("param = %d\n", param);
}
int main(void)
{
func(42); /* line 8 */
return 0;
}

In the following, I'll use quotation marks to delimit chunks of code.

The expression "42" on line 8 is an *argument* (not a parameter).
That expression is evaluated, and the result is assigned to "param",
which is a *parameter* (not an argument). The parameter "param",
which is an object, is created as part of the function call. The
result of evaluating the argument (an expression) is assigned to the
parameter (an object).

An argument and a parameter are two very different things. The
argument doesn't become, and is not converted to, the parameter; the
argument's value is assigned to the parameter.

I believe there's some ambiguity in the standard about just when the
parameter object is created. One passage implies it's created during
the execution of line 8, before "func" is actually called; another
implies that it's created during the execution of "func" itself, just
after execution passes the opening "{". But that ambiguity is not
really such a big deal; since nothing can access that object during
the window of ambiguity.

So the question we seem to be discussing is this: is there an lvalue
on line 8? The answer is clearly no.

What is an lvalue? Ignoring the way both the C90 and C99 standards
have screwed up the definition of the term, an lvalue is an expression
that designates an object. There are several expressions on line 8,
but none of them designate objects.

"42" clearly does not designate an object, so it's not an lvalue.
(The fact that the result of that subexpression is assigned to an
object doesn't make it an lvalue, any more than "43" in "x = 43;" is
an lvalue.)

"func" is a function designator, not an lvalue.

"func(42)" also does not designate an object; it merely yields a
value.

There is a separate question here: is an object created on line 8?
The answer is, I believe, ambiguous. If we assume that the parameter
object is created prior to the function call, then yes, an object is
created on line 8 (but, going back to the previous question, there is
no lvalue on line 8 that refers to that object).

Now if we want to discuss when parameters are created, that's great --
but that discussion doesn't need to consider lvalues.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #57
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>Richard Heathfield wrote:
>>Keith Thompson said:

<snip>

An *argument* is not an object.

Hear, hear. So we are indeed in agreement after all, it seems.

Nonsense. An argument is always an expression, converted into an
object, which is not accessible before entry to the sub-routine.
At that point it can be treated as any other local object.

No, an argument is an expression whose value is *stored* in an object.
An argument and the corresponding parameter are two distinct things.
Please demonstrate such an accessible beast, accessed without first
storing it somewhere. The point is that the creation of the
argument value, and the storage of such for transmission to the
function, is inseparable.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 26 '07 #58
jacob navia wrote:
CBFalconer wrote:
>Richard Heathfield wrote:
>>Keith Thompson said:

<snip>

An *argument* is not an object.
Hear, hear. So we are indeed in agreement after all, it seems.

Nonsense. An argument is always an expression, converted into an
object, which is not accessible before entry to the sub-routine.
At that point it can be treated as any other local object.

That is exactly what I said.

P.S. But even if i would say two plus two is four
I guess Mr heathfield would say "NO. It isn't."
The first sentence is fine. But why spend time sniping at poor
innocent innocuous inconspicuous Richard Heathfield, who has only
corrected errors?

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 26 '07 #59
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>Objects are not lvalues. Lvalues are not objects.
Well, they *should* be, except that the Standard gets this wrong. :-)

(Of course, the Standard is right by definition. It's just that
the C89 definition of "lvalue" is a little flawed, and the C99
definition -- which attempt to fix the problem -- makes things even
worse. Hence my not-entirely-serious claim above. An lvalue
*should* be an "expression that designates an object", as in C89,
with the "designates" being interpreted loosely enough so that *f()
is a "compile time lvalue" even if f() potentially returns NULL,
and simply produces undefined run-time behavior if f() actually
does return NULL.)
>Arguments are not parameters. Parameters are not arguments.
Parameters are objects. Arguments are expressions, not objects.
Indeed.
>What exactly are we arguing about here?

Let's take a simple example:

#include <stdio.h>
void func(int param)
{
printf("param = %d\n", param);
}
int main(void)
{
func(42); /* line 8 */
return 0;
}
Actually, I think we get a better example when we look at
"narrow" arguments, and take a concrete implementation such
as the SPARC or MIPS -- one that uses registers for parameters,
on a machine that has no "narrow" registers. Hence:

void func(char param) /* or: void func(param) char param; */
{
... otherwise the same as above ...
}
>In the following, I'll use quotation marks to delimit chunks of code.

The expression "42" on line 8 is an *argument* (not a parameter).
That expression is evaluated, and the result is assigned to "param",
which is a *parameter* (not an argument). The parameter "param",
which is an object, is created as part of the function call. The
result of evaluating the argument (an expression) is assigned to the
parameter (an object).

An argument and a parameter are two very different things. The
argument doesn't become, and is not converted to, the parameter; the
argument's value is assigned to the parameter.

I believe there's some ambiguity in the standard about just when the
parameter object is created. One passage implies it's created during
the execution of line 8, before "func" is actually called; another
implies that it's created during the execution of "func" itself, just
after execution passes the opening "{". But that ambiguity is not
really such a big deal; since nothing can access that object during
the window of ambiguity.
And if we use that concrete-machine example, we find that the actual
argument -- 42 -- is shoved into register %o0 (on SPARC; different
name on MIPS) at before the call, but is *not* a "char" at this
point. Registers hold full 32 (or 64) bit values. Only after
func() actually starts up is the 32 bit value stored in a narrow,
8-bit object in memory. Hence the *argument* exists *before* the
function begins executing, but the *parameter* exists only *after*
that point (after the "save" instruction, which is extremely-roughly
similar to the x86 "enter" instruction).
>So the question we seem to be discussing is this: is there an lvalue
on line 8? The answer is clearly no. [ discussion snipped ]
Indeed.
>There is a separate question here: is an object created on line 8?
The answer is, I believe, ambiguous. If we assume that the parameter
object is created prior to the function call, then yes, an object is
created on line 8 (but, going back to the previous question, there is
no lvalue on line 8 that refers to that object).

Now if we want to discuss when parameters are created, that's great --
but that discussion doesn't need to consider lvalues.
I think that we have to assume, in principle at least and in practice
on real machines like the SPARC and MIPS, the parameter is "created"
after entry to the function. Optimization often shuffles things
around so that the "creation" winds up using no instructions after
all[%], but this is merely a matter of cleverness-of-implementation.

[% Provided, of course, that the parameter does not require narrowing.
If it does require narrowing, sometimes it can be done "in-register"
with a masking instruction, but that again makes it obvious that
the "parameter creation" happens after the function is called, not
before.]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jun 27 '07 #60
On Tue, 26 Jun 2007 09:28:14 +0200, jacob navia
<ja***@jacob.remcomp.frwrote:
>Richard Heathfield wrote:
>CBFalconer said:
>>Richard Heathfield wrote:
CBFalconer said:
Richard Heathfield wrote:
<snip>
>>>>>For example, there is
>no lvalue in the (pointless but legal) statement:
>>
> toupper((unsigned char)c);
Yes there is, although it is well hidden. The functional parameter.
No, it isn't well hidden. It isn't *there*. Not in that statement.
We must be missing each others points. Where do you think the
conversion of c goes?

It could easily go into a register, but that's beside the point. There's
no object in the statement I presented.

The result of the expression is stored in the stack.
There is an awful lot of generated code that leaves the value of an
evaluated expression in a register without ever placing it in any
memory, let alone a stack.
>(Or its equivalent for the mythical machines without
stack)
I am extremely pleased that my mythical work on the mythical IBM
mainframe results in a very non-mythical paycheck.
>
The object exists, since we can even take its address
within the called function.
Obviously an intermittently true assertion.
Remove del for email
Jun 27 '07 #61
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:
[...]
>What I wrote upthread was:
| No, an argument is an expression whose value is *stored* in an object.
| An argument and the corresponding parameter are two distinct things.

You seemed to disagree with this.

Yes, the evaluation of the argument and the storing of the result in
the parameter always happen together; I suppose they're inseparable
in that sense. But they are two distinct things. An argument is an
expression (see C99 3.3); a parameter is an object (see C99 3.15).
Do you disagree with that?

No, but this discussion is about casting destinations, which cannot
form a LHvalue.
This discussion has drifted considerably. It started out as a
discussion of a proposed extension to allow casts to be treated as
lvalues (presumably if an only if the operand is an lvalue), but this
subthread is about whether a particular expression, a function call,
contains any lvalues.

Do you agree with what I wrote above?
No, an argument is an expression whose value is *stored* in an object.
An argument and the corresponding parameter are two distinct things.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '07 #62

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

Similar topics

31
by: Jacob | last post by:
It is a common recommendation to use "static_cast<SomeType> someInstance" instead of the traditional infamous "(SomeType) someInstance". Should I use the same practice for simple types, i.e....
47
by: sunglo | last post by:
Some time a go, in a discussion here in comp.lang.c, I learnt that it's better not to use a (sometype **) where a (void **) is expected (using a cast). Part of the discussion boiled down to the...
3
by: ramasubramanian.rahul | last post by:
i was reading soemthing about Lvalues Rvalues and modifiable Lvalues.... i am confused now... like for eg int *y , x ; y = &x ; in the second is x a lvalue or rvalue any pointers on some good...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
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...
0
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...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

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.