473,809 Members | 2,876 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 2828
In article <ft************ *************** *****@4ax.com>,
Mark McIntyre <ma**********@s pamcop.netwrote :
long long a;
char *n;

(char *)a = n;
>>Why are casts not lvalues? What TECHNICAL reasons exist for that?
That is my question.
>Because its meaningless in my view.
C constructs are no natural phenomena. They are meaningful if people
assign meaning to them. And several compilers *have* assigned meaning
to casts as lvalues,
>What exactly does the above do?
I believe that it's intended to be equivalent to "a = (long long)n'.
As such, it's not very useful. Some more complicated uses are more
obviously useful, as I've noted elsewhere.

-- Richard
--
"Considerat ion shall be given to the need for as many as 32 characters
in some alphabets" - X3.4, 1963.
Jun 24 '07 #11
jacob navia <ja***@jacob.re mcomp.frwrites:
Richard Heathfield wrote:
>jacob navia said:
>>Continuing the discussion about casts, I would like to know
your opinions about the hairy subject of casts as lvalues
It isn't a matter of opinion. They're not legal C. A cast yields a
value, but not an lvalue.
<snip>
>>What are the problems of doing this?
It doesn't compile.
>>I mean not the usual
"the standard says so" but what problems would arise within the
language if this would be accepted?
Implementors jumped at C89 like a pack of starving stoats on a
squirrel. But they have stayed away from C99 in droves. I don't see
them suddenly all agreeing to support a particular extension, all
with the same syntax and semantics. So the fundamental problem would
be that your proposal wouldn't be accepted.

But this is just politics. I do not want to do any proposal nor do
I want to modify anything. I just want to know what TECHNICAL problems
could arise if that extension (that is provided at least by the
compilers I mentioned) would be part of the language.

Why are casts not lvalues? What TECHNICAL reasons exist for that?
That is my question.
Why *should* casts be lvalues?

For any proposed addition to the language, the burden is on its
advocates to demonstrate that its advantages outweigh the costs of
updating the standard *and* of updating every implementation to
support it.

The main technical problem, in my opinion, is the difficulty of
defining the semantics in all possible cases, something that must be
done if this is to become a language feature. I see no particular
advantage that outweighs this difficulty; I know of no use of
cast-as-lvalue that can't be written equivalently in legal C.

A cast specifies a conversion of a given value (the result of
evaluating an expression) to a specified type. That's relatively
simple to describe and to understand. Allowing casts as lvalues would
require a much more complex model of what casts mean.

I presume you're proposing that a cast would be an lvalue only if the
operand is itself an lvalue. That's just one of the many details that
must be specified before any such proposal can be taken seriously.

Even if such a feature were added to a future version of the standard,
there's a real risk that some obscure corner case could be neglected,
leading to a flaw in the standard. In two attempts a decade apart,
the commitee hasn't even managed to come up with a coherent definition
of the word "lvalue".

--
Keith Thompson (The_Other_Keit h) 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 24 '07 #12
[from article <46************ **********@news .orange.fr>: gcc accepts:]
>>int main(void)
{
long long a;
char *n;

(char *)a = n;
}
In article <f5***********@ pc-news.cogsci.ed. ac.uk>
Richard Tobin <ri*****@cogsci .ed.ac.ukwrote:
>Gcc has, I think, always warned about this if you give enough flags,
Indeed.
>and seems to reject it by default in recent versions.
Yes. This illustrates one of the dangers of relying on compiler
extensions: the compiler-writer may eventually realize the folly
of that particular extension, and remove it. (The extension, not
the folly. :-) )

GCC's old definition of (cast)obj = expr was:

((cast)(obj = (T)(expr)))

where T is the type of the object "obj", -- so the code above, with
"a" being "long long", really "meant":

(char *)(a = (long long)n);

Many programmers seemed to have expected it to mean:

*(char *)&a = n;

which, on a typical 32-bit-pointer, 64-bit-"long long" machine,
sets just half of the object "a", leaving the other half unmodified.
GCC's old interpretation sets all 64 bits. The overly-clever
programmer, believing it set only 32 bits, set the other 32 bits
to something useful first, and then was surprised when those bits
were clobbered.

(If you use Standard C to write "what you mean", you will not be
surprised by whatever bizarre interpretation some compiler-writer
uses for his or her particular extension.)
>I've always thought its use in implementing a "program counter"
variable was reasonable, where a generic pointer is cast to various
types and incremented by the same amount, e.g.

op = *((operator *)pc)++;
switch(op)
{
...
case ADD:
arg1 = *((int *)pc)++;
arg2 = *((int *)pc)++;
whatever = arg1 + arg2;
...

But those writing this style of code can easily enough work around it.
Yes -- and, assuming "void *pc" for the above and that "operator" is
a typedef-name for a type smaller than plain "int", the above tends
to malfunction on various machines. So it might not be the best
way to write the code, even with the more verbose workaround:

op = *(operator *)pc, pc = (unsigned char *)pc + sizeof(operator );
switch (op)
{
...
case ADD:
arg1 = *(int *)pc, pc = (unsigned char *)pc + sizeof(int);
arg2 = *(int *)pc, pc = (unsigned char *)pc + sizeof(int);
whatever = arg1 + arg2;

where the comma-expression versions above might be hidden behind
a macro and then modified a bit:

#define FETCH(ty, pc) \
(pc = (unsigned char *)(pc) + sizeof(ty), ((ty *)pc)[-1])

Note: giving "pc" type "unsigned char *" simplifies this even
further:

#define FETCH(ty, pc) (((ty *)(pc += sizeof(ty)))[-1])

switch (FETCH(operator , pc)) {
...
case ADD:
arg1 = FETCH(int, pc);
whatever = arg1 + FETCH(int, pc);
...

The alignment trap remains, however: for this to work in general,
the pointer must remain aligned for each type "ty". The simplest
way to guarantee such alignment is to use just a single type, in
this case, "int". If "pc" is always going to refer to "int"s, we
can remove the FETCH macro's "ty" argument, change "pc" to "int
*", and simply use *pc++ -- and thus remove all need for the FETCH
macro itself.
--
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 24 '07 #13
On Jun 25, 8:54 am, Joe Wright <joewwri...@com cast.netwrote:
Harald van Dijk wrote:
jacob navia wrote:
Continuing the discussion about casts, I would like to know
your opinions about the hairy subject of casts as lvalues, i.e.
[...]
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?
int a = 1;
void f(double *d) {
if (a == 1) *d = 2;
if (a == 2) *d = 0;
}
int main(void) {
f(&(double) a);
return a;
}
What would this program return?

It doesn't compile here. You seem to want to pretend a is a double.
Did you read the text you quoted? The point of
this thread is to ask what problems would occur
if the above code were made legal.

Jun 24 '07 #14
jacob navia wrote:
>
Continuing the discussion about casts, I would like to know
your opinions about the hairy subject of casts as lvalues, i.e.
I don't like it because the semantics are srewed up.
An lvalue converted to a different type,
refers to memory that was never reserved.

--
pete
Jun 24 '07 #15
jacob navia wrote:
>
.... snip ...
>
Why are casts not lvalues? What TECHNICAL reasons exist for that?
That is my question.
A cast requires a destination (i.e. a lvalue) to receive the
converted object. Without a destination, such does not exist.

--
<http://www.cs.auckland .ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfoc us.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 25 '07 #16
jacob navia wrote:
>
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.
Don't know about MSVC, but gcc (later versions) will also reject
this. A cast cannot be a lvalue. Also you have the types
confused.

--
<http://www.cs.auckland .ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfoc us.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 25 '07 #17
CBFalconer said:
jacob navia wrote:
>>
... snip ...
>>
Why are casts not lvalues? What TECHNICAL reasons exist for that?
That is my question.

A cast requires a destination (i.e. a lvalue) to receive the
converted object.
No, it doesn't. No object is converted by a cast, and casts do not
*require* lvalues to receive their results. For example, there is no
lvalue in the (pointless but legal) statement:

toupper((unsign ed char)c);

--
Richard Heathfield <http://www.cpax.org.uk >
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 25 '07 #18
On Sun, 24 Jun 2007 21:13:40 +0200, jacob navia
<ja***@jacob.re mcomp.frwrote in comp.lang.c:
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.
I just tried this with Visual Studio 2005 Express, and indeed you have
to set the warning level to maximum (/W4) to even get it to issue a
misleadingly incorrectly worded error massage:

"warning C4213: nonstandard extension used : cast on l-value"

....but it still produces a 32-bit executable. When I initialize a to
a value and n to NULL, it sets the low 32 bits of a to its
representation of a NULL pointer (0), and leaves the high 32 bits
unchanged.

The only version of gcc that I have installed at the moment is 3.4.2,
(mingw), and it gives me these two diagnostics:

"warning: cast to pointer from integer of different size"
"warning: use of cast expressions as lvalues is deprecated"
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?
What do you do with:

(char *)(3LL + 5LL) = n;

....???
Apparently gcc and msvc are still used, and this doesn't seem
to produce any big problems.
Well, actually it does produce the big problem of continuing to allow
programmers to write incorrect and quite possibly unsafe code. What
happens when they cast a value with a narrower representation to one
with a wider representation?
Thanks in advance for your comments, and I thank all people
that participated in the discussion yesterday.
Personally, I'm against this. If the cast is to a type with more bits
than the original, you risk overwriting memory incorrectly, with all
of the defect and security issues that involves. If the cast is to a
type with more bits than the original, you risk creating an invalid
trap value in the object.

And, of course, if somebody really needs to do this, or at least
thinks that they do, it is perfectly legal to write:

*(char *)(&a) = n;

This is hideously ugly and stands out like a sore thumb, as well it
should.

If you start down this path, you open a can of worms that means you
need to scrutinize all operators that currently yield (r)values rather
than lvalues. Where and why do you stop?

Given:

void func(int *ip);

What should happen with:

int x = 3;
func(&(x + 2));

You could indeed do this, at the expense of turning C into BASIC (or
other languages), that will construct a temporary object for you.

I just don't think the gain is worth the change, especially since
there is a valid way to write a statement that does the same thing.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Jun 25 '07 #19
On Mon, 25 Jun 2007 00:17:39 +0200, in comp.lang.c , jacob navia
<ja***@jacob.re mcomp.frwrote:
>Mark McIntyre wrote:
>On Sun, 24 Jun 2007 23:20:03 +0200, in comp.lang.c , jacob navia
<ja***@jacob.r emcomp.frwrote:

(of
long long a;
char *n;

(char *)a = n;
)
>>Why are casts not lvalues? What TECHNICAL reasons exist for that?
That is my question.

Because its meaningless in my view. What exactly does the above do?
Moves the contents of n (an address) into the memory locations of a,
with you so far...
>that can hold a pointer is sizeof(void *) <= sizeof(long long);
.... but not here.
The value of n is assigned to a. Ok. If n is larger than *a, there's a
memory overwrite. How does this 'cast' help with this???
>I am not saying that this is nice/the best thing since sliced bread
but that is what it does.
I probably misunderstand, because to me the above is gibberish.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jun 25 '07 #20

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

Similar topics

31
2316
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. instead of: double fraction = (double) n / total; should I write this?
47
2672
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 rule: if I cast a (sometype **) to a (void **) I am making a number of assumptions about the implementation's (void **) representation and length. Specifically, if I do the above cast I'm assuming that a (sometype **) and a (void **) have the same...
3
2728
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 reading on lvalues and rvalues on the web ?? thanks in advance Kind Regard
0
9600
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
10376
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10375
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10114
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
7651
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
5548
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
5686
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4331
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
3
3011
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.