By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,720 Members | 2,096 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,720 IT Pros & Developers. It's quick & easy.

Avoiding "use of cast expressions in lvalues is deprecated"

P: n/a
Hi guys,

We have the following macro:

#define NEXT(type,p) (*((type*)(p))++)

It provides a way to poke variable sized data into an array of pcode
for a simple VM.
e.g,

NEXT(byte,pcode) = PUSH;
NEXT(int,pcode) = constant;

But this technique now seems to be deprecated. It seems fairly safe to
me (pointers can always be interconverted) and I can't see any obvious
and efficient way to get around the error (particularly in the pcode
interpreter itself)

thanks in advance,
Steve Donovan.

Sep 19 '06 #1
Share this Question
Share on Google+
23 Replies


P: n/a
st*************@gmail.com wrote:
Hi guys,

We have the following macro:

#define NEXT(type,p) (*((type*)(p))++)

It provides a way to poke variable sized data into an array of pcode
for a simple VM.
e.g,

NEXT(byte,pcode) = PUSH;
NEXT(int,pcode) = constant;

But this technique now seems to be deprecated.
It's never been valid in standard C, using cast expressions as lvalues
was a GNU extension.
It seems fairly safe to
me (pointers can always be interconverted)
So can int and double, but you wouldn't expect ((int) d)++ to compile
when d is declared as double, would you? Why should pointers be any
different? (Before answering, think about it a little bit more.)
and I can't see any obvious
and efficient way to get around the error (particularly in the pcode
interpreter itself)
"Efficient"? It is quite likely that rewriting the code with separate
write and increment statements will generate identical object code,
assuming you're compiling with optimisations enabled, and a decent
compiler.

Instead of

*((int*) p)++ = k;

Use

*(int *) p = k;

followed by

p = (int *) p + 1; /* if p is of type void* */

or

p += sizeof(int); /* if p is of type char* or another byte-sized type
*/

You should really also handle the different possibilities for the size
and representation of an int, and any alignment issues, if you want to
make sure the code is portable to other platforms, but those are
separate subjects.

Sep 19 '06 #2

P: n/a
In article <11**********************@e3g2000cwe.googlegroups. com>,
<st*************@gmail.comwrote:
>#define NEXT(type,p) (*((type*)(p))++)

It provides a way to poke variable sized data into an array of pcode
for a simple VM.
[...]
>But this technique now seems to be deprecated.
It's never been standard C. It was allowed by some early C compilers
and in some drafts of the first ANSI C standard, and is allowed by gcc
as an extension.
>It seems fairly safe to
me (pointers can always be interconverted)
Pointers can be interconverted on most implementations. It may not
work if different kinds of pointer have different representations
(what's it going to store back in p?) and of course it will only work
if there are no alignment problems for the types and processor in
question.

On those systems where it "ought" to work, you can usually achieve the
same effect by using a union type:

union {
int *i;
char *c;
} p;

ii = p.i++;
cc = p.c++;

or by using a "generic" unsigned char pointer, perhaps something like:

unsigned char *p, *t;

#define NEXT(type, p, t) ((t) = (p), p += sizeof(type), (type *)*(t))

-- Richard
Sep 19 '06 #3

P: n/a
Richard Tobin wrote:
It's never been standard C. It was allowed by some early C compilers
and in some drafts of the first ANSI C standard, and is allowed by gcc
as an extension.
Now that I never knew - sometimes it's unwise to learn a language from
a compiler.
#define NEXT(type, p, t) ((t) = (p), p += sizeof(type), (type *)*(t))
Thanks guys, that's exactly what I needed - the standard way to think
about
the problem, and the pitfalls of doing it the cowboy method.

steve d.

Sep 19 '06 #4

P: n/a
st*************@gmail.com wrote:
Hi guys,

We have the following macro:

#define NEXT(type,p) (*((type*)(p))++)

It provides a way to poke variable sized data into an array of pcode
for a simple VM.
e.g,

NEXT(byte,pcode) = PUSH;
NEXT(int,pcode) = constant;

But this technique now seems to be deprecated. It seems fairly safe to
me (pointers can always be interconverted) and I can't see any obvious
and efficient way to get around the error (particularly in the pcode
interpreter itself)

thanks in advance,
Steve Donovan.
In my opinion, a compiler that introduces an extension should be
fair to the users that use that extension and never take it back
without a means to the users to keep their code as is.

It is apparently not the way gcc works, maybe as a result of the
C++ habit of invalidating code bases. In C++ is a daily problem that
code that works with version x.x of the compiler will stop working
in version x.x+1. Now the compiler is more compliant with the
standards, the compiler people will argue. It rejects previously working
code.

This has been exported to C also. Extensions that worked are now
discontinued.

jacob
Sep 19 '06 #5

P: n/a
posted:
#define NEXT(type,p) ( *((type*)(p))++)
Basically you just want to advance a pointer by sizeof(type) amount of bytes.
Beware of alignment issues. Here's an alternative macro which is valid C
(i.e. it doesn't use the result of a cast as an L-value):

#define NEXT(type,p) ( *( *(type**)&(p) )++ )

But this won't work with more complicated pointers (such as:

int (*(*)())[4]

(A pointer to a function which returns a pointer to an array.)

Here's the beginnings of a more elaborate solution so that you can use more
elaborate pointers (...although I didn't finish it).

#include <stddef.h>

void const volatile *AdvanceBytes(void const volatile *volatile *const p,
size_t const quant_bytes)
{
void const volatile *retval = (char*)p;

(char*)*p += quant_bytes; /* Problem here */
}

#define NEXT(type,p) (type*)AdvanceBytes(p

--

Frederick Gotham
Sep 19 '06 #6

P: n/a
Frederick Gotham posted:
Here's an alternative macro which is valid C (i.e. it doesn't use the
result of a cast as an L-value):

#define NEXT(type,p) ( *( *(type**)&(p) )++ )

Wups, I just realised that the following code invokes UB:

#define NEXT(type,p) ( *( *(type**)&(p) )++ )

char var, *p = &var;

NEXT(double,p);

because sizeof(double*) might differ from sizeof(char*).

--

Frederick Gotham
Sep 19 '06 #7

P: n/a
The following is almost, but not completely, entirely unlike a topical post;
I think it's still related to C specifically enough to be interesting here,
but you have been warned.

jacob navia wrote:
In my opinion, a compiler that introduces an extension should be
fair to the users that use that extension and never take it back
without a means to the users to keep their code as is.
Fairness is in the eye of the beholder. In my opinion, compiler writers have
a duty to clearly inform their users of features that aren't standard and
what their policies on maintaining such features are, so that users can make
an informed decision -- but that's all.

There are good reasons why designers choose not to make backwards
compatibility absolute, one of the most prominent being maintainability. It
is deceptively easy to ruin your chances of remaining successful by turning
your program (or indeed your language) into a pile of privileged historical
accidents. Pundits might argue C itself suffers at least partially from
exactly this problem.

Absolute backwards compatibility is unreasonable. Even Microsoft, one of the
the most backwards companies... I mean, one of the most backwards-compatible
companies in the world[*], hasn't always been able to ensure that every
program that ran on one version of their operating systems ran on the next
-- sometimes things just have to give.

And Microsoft is catering to people who are unable to change their programs
themselves and mostly unwilling to have them changed: the end users. If end
users cannot be fully insulated from changes, how is it reasonable to expect
developers to be?
It is apparently not the way gcc works, maybe as a result of the
C++ habit of invalidating code bases.
This is a direct result of the C++ standard needing several years to
stabilize. Compiler writers are hardly to blame, unless you propose they
should have written compilers capable of emulating every previous version of
themselves (which is certainly possible, but after a moment's thought also a
good illustration of why this is problematic at best and meaningless at worst).
In C++ is a daily problem that code that works with version x.x of the
compiler will stop working in version x.x+1. Now the compiler is more
compliant with the standards, the compiler people will argue. It rejects
previously working code.
Again: blame C++ for this, not the C++ compilers. If your language isn't
stable, how can you expect your code to be? On the other hand: if your
language *is* stable, how reasonable is it to expect that the code you write
outside the stable base maintains its semantics?
This has been exported to C also. Extensions that worked are now
discontinued.
Oh, it's not just extensions. Aren't you just appalled that you can't
compile some K&R C code with the latest versions of gcc? As if rewriting a
fully functioning program to conform to ANSI improves it! How much would it
have cost to keep full K&R support in the compiler, anyhow?

The regrettable result of changing the language is that developers are kept
busy for no immediate reward. The less tangible rewards are a compiler
that's easier to maintain and an actual incentive to move to conforming
code, which is easier to maintain in the long run.

Those people who'd argue that they don't care enough about a maintainable
compiler or conforming code are free to keep using the existing version or
branch of their compiler for as long as it will serve them. TANSTAAFL.

S.[*]I know MS bashing is considered unrefined these days, but this was too
good to pass up.
Sep 19 '06 #8

P: n/a
Skarmander wrote:
Oh, it's not just extensions. Aren't you just appalled that you can't
compile some K&R C code with the latest versions of gcc? As if rewriting
a fully functioning program to conform to ANSI improves it! How much
would it have cost to keep full K&R support in the compiler, anyhow?

Wow, this is good news, I did not know that!!!

I am finishing the lcc-lin32 version of lcc-win32 for linux.
It features a 32 bit compiler, much faster than gcc (approx
a speedup of 10 times).

This means I will get all those "clients" dissatisfied with
gcc.

I wanted to introduce the same extension as gcc what lvalued
casts is concerned several years ago, but a huge OUTCRY in
the lcc group refrained me from doing that...

Maybe I should try again :-)
Sep 19 '06 #9

P: n/a
On Tue, 19 Sep 2006 12:39:14 +0200, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>In my opinion, a compiler that introduces an extension should be
fair to the users that use that extension and never take it back
without a means to the users to keep their code as is.
Where possible, given new requirements placed upon the compiler by
standardisation.
>
It is apparently not the way gcc works, maybe as a result of the
C++ habit of invalidating code bases. In C++ is a daily problem that
code that works with version x.x of the compiler will stop working
in version x.x+1.
This from the man crying out for gets() to be removed from the C
standard. Double standards as well as inflammatory disinformation.
>Now the compiler is more compliant with the
standards, the compiler people will argue. It rejects previously working
code.
Certainlly if a standardisation process defines a meaning for specific
functionality, or makes certain functionality prohibited, its entirely
correct that compiler writers should attempt to match this.
>This has been exported to C also. Extensions that worked are now
discontinued.
Sure, if they conflict with standard behaviour.
--
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
Sep 19 '06 #10

P: n/a
On Tue, 19 Sep 2006 21:51:56 +0200, in comp.lang.c , Skarmander
<in*****@dontmailme.comwrote:
>Oh, it's not just extensions. Aren't you just appalled that you can't
compile some K&R C code with the latest versions of gcc? As if rewriting a
fully functioning program to conform to ANSI improves it! How much would it
have cost to keep full K&R support in the compiler, anyhow?
I guess the standards committee would argue that its the price one
pays for improving the typechecking system. Presumably there are those
in world would have their cake and eat it, that would insist they want
safer code but don't want to pay the cost . The same people probably
insist its their right to drive rusty pollution emitting physically
unsound trucks, after all it was good enough for grandaddy up in the
hills fifty years ago.
>The regrettable result of changing the language is that developers are kept
busy for no immediate reward.
Speak for yourself! Good money in upgrading s/w to match modern
standards.

--
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
Sep 19 '06 #11

P: n/a
Mark McIntyre wrote:
On Tue, 19 Sep 2006 21:51:56 +0200, in comp.lang.c , Skarmander
<in*****@dontmailme.comwrote:
>Oh, it's not just extensions. Aren't you just appalled that you can't
compile some K&R C code with the latest versions of gcc? As if rewriting a
fully functioning program to conform to ANSI improves it! How much would it
have cost to keep full K&R support in the compiler, anyhow?

I guess the standards committee would argue that its the price one
pays for improving the typechecking system.
But perfect programs don't need an improved typechecking system. It already
works, so we should leave it alone. Of course, I do expect my compiler
vendor to keep improving the compiler, just not the language it compiles.
Those ANSI C folks just missed the boat when K&R laid down the law.
>The regrettable result of changing the language is that developers are kept
busy for no immediate reward.

Speak for yourself! Good money in upgrading s/w to match modern
standards.
Yes, quite true. The "reward" I spoke of was in relation to the code
rewritten in the process (under the assumption that it's perfect, of
course), not the developers doing the rewriting... I should have been less
ambiguous.

S.
Sep 19 '06 #12

P: n/a
jacob navia posted:
I wanted to introduce the same extension as gcc what lvalued
casts is concerned several years ago, but a huge OUTCRY in
the lcc group refrained me from doing that...

What's wrong with the following?

#define L_VALUE_CAST(type,expr) (*(type*)&(expr))

Of course, it won't work with more complicated types such as arrays and
function pointers, but it's a start.

--

Frederick Gotham
Sep 19 '06 #13

P: n/a
jacob navia wrote:
Skarmander wrote:
>Oh, it's not just extensions. Aren't you just appalled that you can't
compile some K&R C code with the latest versions of gcc? As if
rewriting a fully functioning program to conform to ANSI improves it!
How much would it have cost to keep full K&R support in the compiler,
anyhow?
Wow, this is good news, I did not know that!!!
Don't get your hopes up. If people flock to a new compiler, it's not going
to be for K&R support.
I am finishing the lcc-lin32 version of lcc-win32 for linux.
It features a 32 bit compiler, much faster than gcc (approx
a speedup of 10 times).
Good for you. It may have niche uses.

Well, don't get me wrong, compilation speed is one important aspect of a
compiler, but I won't be recompiling my Ubuntu distribution with it any time
soon. Maybe in a year or so, when other people have gathered experiences.

Actually, make that two years.
This means I will get all those "clients" dissatisfied with
gcc.
Really? You mean to say your compiler has none of the issues specified here
http://gcc.gnu.org/onlinedocs/gcc-4....ibilities.html
*and* is compatible with gcc in other respects?

I take it you're also going to make your compiler free for commercial or
educational use? Oh, and where can I download the source, in case I find a
bug I need to fix yesterday?

Hmm, well, you're not going to get *all* clients dissatisfied with gcc. And
don't forget there are other contenders for the "faster than gcc" title,
even on Linux.
I wanted to introduce the same extension as gcc what lvalued
casts is concerned several years ago, but a huge OUTCRY in
the lcc group refrained me from doing that...

Maybe I should try again :-)
That would be evil[*]. There are perfectly portable ways of writing what you
can do with lvalued casts (leaving aside that some of it may nevertheless be
implementation-defined). For God's sake, it's not even hard to do! If you
deliberately implement this as an extension now, when even gcc is moving
away from it (with plenty of advance warning, I might add), you encourage
people to make (continued or new) use of a pointless extension. The result
is vendor lock-in, which is good for you, and proliferation of gratuitously
unportable code written in not-quite-C, which is good for people who don't
care about quality code. Neither of this is good for the world as a whole.

S.[*]I use the word in a strictly utilitarian sense.
Sep 19 '06 #14

P: n/a
st*************@gmail.com wrote:
Richard Tobin wrote:
It's never been standard C. It was allowed by some early C compilers
and in some drafts of the first ANSI C standard, and is allowed by gcc
as an extension.

Now that I never knew - sometimes it's unwise to learn a language from
a compiler.
No, it's _always_ unwise to learn a language from a compiler. The C
standard allows greate freedom in implementation, but also requires
them to make (and document) choices. As a consequence, the
implementation you 'learn' on one machine need not be the same as
others.
#define NEXT(type, p, t) ((t) = (p), p += sizeof(type), (type *)*(t))
#define NEXT(type, p) \
( * (type *) ( (p += sizeof(type)) - sizeof(type) ) )

Both assume that p is a pointer to a character type (amongst other
things.)
Thanks guys, that's exactly what I needed - the standard way to think
about the problem, and the pitfalls of doing it the cowboy method.
Well, it still has problems that the conversion of p to a type *
pointer need
not be defined (e.g. alignment). There are plenty of implementations
where
this method will fail miserably.

--
Peter

Sep 19 '06 #15

P: n/a
Mark McIntyre wrote:
On Tue, 19 Sep 2006 12:39:14 +0200, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:

>>In my opinion, a compiler that introduces an extension should be
fair to the users that use that extension and never take it back
without a means to the users to keep their code as is.


Where possible, given new requirements placed upon the compiler by
standardisation.
>>It is apparently not the way gcc works, maybe as a result of the
C++ habit of invalidating code bases. In C++ is a daily problem that
code that works with version x.x of the compiler will stop working
in version x.x+1.


This from the man crying out for gets() to be removed from the C
standard. Double standards as well as inflammatory disinformation.
The proposal I published in comp.std.c was to make an
Appendix to the standard where obsolescent features would be
described, that are no longer part of the official standard.

Nowhere I wanted to just delete gets(). Users that want to use it
could use it using a compatibillity library based on that Appendix.
Whether an implementation follows that (non-normative) standard
Appendix is up to the implementation. Since all implementations have
gets() NOW, building such a compatibility library would be
very easy and most vendors would have it.

You are just misrepresenting my proposal, and then... YOU accuse
me of "double standards"!!!
Sep 20 '06 #16

P: n/a
jacob navia wrote:
Mark McIntyre wrote:
On Tue, 19 Sep 2006 12:39:14 +0200, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:

>In my opinion, a compiler that introduces an extension should be
fair to the users that use that extension and never take it back
without a means to the users to keep their code as is.

Where possible, given new requirements placed upon the compiler by
standardisation.
>It is apparently not the way gcc works, maybe as a result of the
C++ habit of invalidating code bases. In C++ is a daily problem that
code that works with version x.x of the compiler will stop working
in version x.x+1.

This from the man crying out for gets() to be removed from the C
standard. Double standards as well as inflammatory disinformation.

The proposal I published in comp.std.c was to make an
Appendix to the standard where obsolescent features would be
described, that are no longer part of the official standard.

Nowhere I wanted to just delete gets(). Users that want to use it
could use it using a compatibillity library based on that Appendix.
Whether an implementation follows that (non-normative) standard
Appendix is up to the implementation. Since all implementations have
gets() NOW, building such a compatibility library would be
very easy and most vendors would have it.

You are just misrepresenting my proposal, and then... YOU accuse
me of "double standards"!!!
If gets() is removed from the normative text of the standard, a
conforming implementation cannot declare it in <stdio.h>, and must
accept any user definitions of gets.

Sep 20 '06 #17

P: n/a
Harald van Dijk wrote:
If gets() is removed from the normative text of the standard, a
conforming implementation cannot declare it in <stdio.h>, and must
accept any user definitions of gets.
Yes, of course. Why should it be kept in stdio?
It should be in "obsolete.h", the header describing
"obsolete.lib" or "obsolete.a". To use gets, people
would just add
#include "obsolete.h"
and link with the appropiate library.

This is not just *forcing* people to avoid gets(), but
avoiding any official support for it, what is a different
approach.

Sep 20 '06 #18

P: n/a
jacob navia <ja***@jacob.remcomp.frwrites:
Harald van Dijk wrote:
>If gets() is removed from the normative text of the standard, a
conforming implementation cannot declare it in <stdio.h>, and must
accept any user definitions of gets.

Yes, of course. Why should it be kept in stdio?
It should be in "obsolete.h", the header describing
"obsolete.lib" or "obsolete.a". To use gets, people
would just add
#include "obsolete.h"
and link with the appropiate library.

This is not just *forcing* people to avoid gets(), but
avoiding any official support for it, what is a different
approach.
So you want to break existing code (by requiring it to add a #include
directive for a new header) *and* keep gets(). Sounds like the worst
of both worlds to me.

--
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.
Sep 20 '06 #19

P: n/a
Keith Thompson wrote:
jacob navia <ja***@jacob.remcomp.frwrites:
>>Harald van Dijk wrote:
>>>If gets() is removed from the normative text of the standard, a
conforming implementation cannot declare it in <stdio.h>, and must
accept any user definitions of gets.

Yes, of course. Why should it be kept in stdio?
It should be in "obsolete.h", the header describing
"obsolete.lib" or "obsolete.a". To use gets, people
would just add
#include "obsolete.h"
and link with the appropiate library.

This is not just *forcing* people to avoid gets(), but
avoiding any official support for it, what is a different
approach.


So you want to break existing code (by requiring it to add a #include
directive for a new header) *and* keep gets(). Sounds like the worst
of both worlds to me.
Yea of course I am always wrong.

The idea that wth some flag like
-std=c99compatible

that include file is automatically included doesn't come to your
mind at all as in

#ifdef __STDC99_COMPATIBLE__
#include "compatible.h"
#endif

in stdio.h

and the compiler would set __STDC99_COMPATIBLE__
if that flag was passed at compile time
Sep 20 '06 #20

P: n/a
jacob navia said:

<snip>
Yea of course I am always wrong.
That's a habit that you might want to try breaking. It would do you the
world of good.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Sep 20 '06 #21

P: n/a
On Tue, 19 Sep 2006 23:57:10 +0200, in comp.lang.c , Skarmander
<in*****@dontmailme.comwrote:
>But perfect programs don't need an improved typechecking system. It already
works, so we should leave it alone.
Nor do they need to be made Y2K compliant, or deal with the 2038
epoch, or with long filenames, or with supersize files or with
changing inputs...

hmm. There's a flaw here somewhere...
>Speak for yourself! Good money in upgrading s/w to match modern
standards.
Yes, quite true. The "reward" I spoke of was in relation to the code
rewritten in the process (under the assumption that it's perfect, of
course), not the developers doing the rewriting...
I wasn't aware code had emotions, let alone felt rewarded by being
perfect!
>I should have been less ambiguous.
er...
--
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
Sep 20 '06 #22

P: n/a
On Wed, 20 Sep 2006 07:31:09 +0200, in comp.lang.c , jacob navia
<ja***@jacob.remcomp.frwrote:
>Mark McIntyre wrote:
>>
This from the man crying out for gets() to be removed from the C
standard. Double standards as well as inflammatory disinformation.

The proposal I published in comp.std.c was to make an
Appendix to the standard where obsolescent features would be
described, that are no longer part of the official standard.
Then you have frequently misrepresented yourself and your request in
CLC. I'm unsurprised.
>You are just misrepresenting my proposal, and then... YOU accuse
me of "double standards"!!!
No, I'm reporting what I have observed you have claimed to want to do.

You can hardly blame CLC regulars if you surround your actual point
with so much noise and fury that whats left seems to signify nothing.
--
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
Sep 20 '06 #23

P: n/a
Mark McIntyre wrote:
On Tue, 19 Sep 2006 23:57:10 +0200, in comp.lang.c , Skarmander
<in*****@dontmailme.comwrote:
>Yes, quite true. The "reward" I spoke of was in relation to the code
rewritten in the process (under the assumption that it's perfect, of
course), not the developers doing the rewriting...

I wasn't aware code had emotions, let alone felt rewarded by being
perfect!
Maybe you should get in touch with your code more often.
>I should have been less ambiguous.

er...
Le sigh.

S.
Sep 21 '06 #24

This discussion thread is closed

Replies have been disabled for this discussion.