gcc: What's illegal about this ?

R

Richard Eich

I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...

sum += *((unsigned short *)iphp)++ ;

....but I don't see what the problem is. gcc 3.4.3 isn't bother by
it, either.

Machine specifics:

$ uname -a
Linux tmxnw-fc6 2.6.22.9-61.fc6 #1 SMP Thu Sep 27 18:48:03 EDT 2007
i686 i686 i386 GNU/Linux

$ gcc --version
gcc (GCC) 4.1.2 20070626 (Red Hat 4.1.2-13)
 
B

Ben Pfaff

Richard Eich said:
I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...

sum += *((unsigned short *)iphp)++ ;

The part that GCC is complaining about is this:
((unsigned short *)iphp)++
which attempts to increment the result of a cast. The result of
a cast is never an lvalue, so you can't increment it. (GCC used
to have an extension that permits this, but it was removed.)

Perhaps you really mean:
sum += (*((unsigned short *)iphp))++ ;
 
H

Harald van Dijk

I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...

sum += *((unsigned short *)iphp)++ ;

...but I don't see what the problem is. gcc 3.4.3 isn't bother by it,
either.

(unsigned short *)iphp is not an lvalue. Where do you want to store
(unsigned short *)iphp + 1? Presumably, you want to store it in iphp. If
you want that, write that.

sum += *((unsigned short *)iphp);
iphp = ((unsigned short *)iphp) + 1;

You can consider it similar to
int i;
(i + 1) = -1;
(double) i = 1.5;
 
Y

ymuntyan

I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...

sum += *((unsigned short *)iphp)++ ;

...but I don't see what the problem is. gcc 3.4.3 isn't bother by
it, either.

Your code is invalid, result of a cast is not an lvalue
(and hence not something you can apply ++ to). Quoting
http://gcc.gnu.org/gcc-3.4/changes.html

"""
The cast-as-lvalue extension has been removed for C++ and
deprecated for C and Objective-C. In particular, code like this:
int i;
(char) i = 5;
or this:
char *p;
((int *) p)++;
is no longer accepted for C++ and will not be accepted for C
and Objective-C in a future version.
"""

And "future version" was 4.something.

Yevgen
 
A

Aaron Hsu

Richard Eich said:
I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...
sum += *((unsigned short *)iphp)++ ;
...but I don't see what the problem is. gcc 3.4.3 isn't bother by
it, either.

I think it would help if you could give us just a bit of context, at least.
 
C

CBFalconer

Aaron said:
I think it would help if you could give us just a bit of context,
at least.

In this case at least, why? That line of code is obviously wrong.
Evem before the very queasy integer to pointer cast.
 
R

Richard Tobin

I need a clue. I'm getting an "invalid lvalue in increment" from gcc
4.1.2 on this line...

sum += *((unsigned short *)iphp)++ ;

...but I don't see what the problem is. gcc 3.4.3 isn't bother by
it, either.

It's an extension in earlier versions of gcc, was accepted by
some other C compilers before the ANSI standard, and was allowed in
early drafts of the ANSI standard, but it not allowed now.

-- Richard
 
Y

ymuntyan

In this case at least, why? That line of code is obviously wrong.
Evem before the very queasy integer to pointer cast.

So context indeed would be helpful, because there is no
integer to pointer cast ;)

Yevgen
 
C

c gordon liddy

Aaron Hsu said:
I think it would help if you could give us just a bit of context, at
least.

My goodness, you've got your open source numbers reversed: 3.4.3 is now
4.3.0.

I think a lot of companies will soon have announcements for a new distro. I
have not heard of any issues with the C part of it, inparticular how it does
with C99. Given that OP needs a compiler updtae of this magnitude, he might
best reconsider his whole configuration. Has he considered a solaris
partition? His C capability would be state of the art.
 
K

Kenny McCormack

It's an extension in earlier versions of gcc, was accepted by
some other C compilers before the ANSI standard, and was allowed in
early drafts of the ANSI standard, but it not allowed now.

-- Richard

What did it do?

As has been pointed out, it doesn't make any sense, so I'm having a hard
time imagining what it did in prior versions of gcc?
 
H

Harald van Dijk

What did it do?

As has been pointed out, it doesn't make any sense, so I'm having a hard
time imagining what it did in prior versions of gcc?

In those versions, (ptrtype) ptrlvalue was treated in some (but not all)
contexts as *(ptrtype *) &ptrlvalue, except without aliasing problems (if
those versions understood aliasing at all).
 
R

Richard Tobin

It's an extension in earlier versions of gcc, was accepted by
some other C compilers before the ANSI standard, and was allowed in
early drafts of the ANSI standard, but it not allowed now.
[/QUOTE]
What did it do?

It's quite straightforward. You want a pointer that points to a
sequence of objects of different types, and you want to retrieve
them one after the other. So you cast the pointer to the desired
type, dereference it (to get the object), and increment it to move
it past the object to the next one.

A typical use is implementing the program counter in a virtual
machine. It points to a mixture of opcodes and operands, where
the size and number of the operands is determined by the opcode:

void *pc;

opcode = *((opcode_t *)pc)++;
switch(opcode)
{
...
case load_integer:
ireg = *((int *)pc)++;
break;
case load_double:
dreg = *((double *)pc)++;
break;
...
}

Obviously you can achieve the same effect by various other more verbose
means, e.g.

char *pc;

opcode = *(opcode_t *)pc;
pc += sizeof(opcode_t);

or

void *pc;

opcode = *(opcode_t)pc;
pc = ((opcode_t)pc) + 1;

but these are not usable in expressions.

If you know that all pointers have the same representation and that
your implementation works in a suitable manner you can do:

union { opcode_t *op; int *i; double *d; ... } pc;

opcode = *pc.op++;
...
ireg = *pc.i++;

In all cases you have to be aware of alignment constraints, of course.

-- Richard
 
R

Richard Tobin

As has been pointed out, it doesn't make any sense, so I'm having a hard
time imagining what it did in prior versions of gcc?
[/QUOTE]
In those versions, (ptrtype) ptrlvalue was treated in some (but not all)
contexts as *(ptrtype *) &ptrlvalue, except without aliasing problems (if
those versions understood aliasing at all).

Though it's similar in effect to that expression, I would have hoped
it didn't rely on the pointer types having to the same representation,
which that does.

I would expect *(ptrtype *)ptrlvalue++ to be interpreted as
*(ptrtype *)ptrlvalue for the purpose of retrieving the value,
and as ptrlvalue = (type_of_ptrlvalue)(((ptrtype *)ptrlvalue) + 1)
for the side effect.

-- Richard
 
H

Harald van Dijk

Though it's similar in effect to that expression, I would have hoped it
didn't rely on the pointer types having to the same representation,
which that does.

Correct. I don't believe gcc has been ported to systems where different
pointer types have different representations (though I would be pleased
if proved wrong on this).
 
C

CBFalconer

So context indeed would be helpful, because there is no
integer to pointer cast ;)

iphp is cast to a pointer. Besides which the ++ operates on the
cast value, which is illegal. If iphp isn't integral things are
even worse.
 
Y

ymuntyan

iphp is cast to a pointer.

It is, but it's a pointer from the very beginning.

char *iphp; // guessed
sum += *((unsigned short *)iphp)++ ;
Besides which the ++ operates on the
cast value, which is illegal.
Yep.

If iphp isn't integral things are
even worse.

Not really.

Yevgen
 
C

CBFalconer

It is, but it's a pointer from the very beginning.

So what? The only conversion available is to a void*, and from a
void* back to the original form. All others are illegal.
char *iphp; // guessed
sum += *((unsigned short *)iphp)++ ;


Not really.

Yes, really. Read the C standard.
 
K

Keith Thompson

CBFalconer said:
So what? The only conversion available is to a void*, and from a
void* back to the original form. All others are illegal.

Conversion from, say, unsigned int* to unsigned short* is specifically
permitted by the standard. It's non-portable and often unsafe (the
result may not be correctly aligned, and byte ordering can make a
difference if you try to dererence it), but it's not illegal.

And in fact one of C's greatest strengths is that it lets you write
non-portable code when you need to.

(The standard doesn't use the term "illegal". In my opinion, the term
is most sensibly applied to things that require a diagnostic, namely
syntax errors and constraint violations.)
 
Y

ymuntyan

So what? The only conversion available is to a void*, and from a
void* back to the original form. All others are illegal.


As people around here say, Wrong.
Yes, really. Read the C standard.

As far as the standard is concerned, both cases would
be wrong. So if you were to compare them, then it's
not using the standard but using the meaning of
((type-name)expression)++ in given implementation (GNU
C). And in that case you don't care whether something
was an integer or a pointer, both can be converted to
each other. Not that it makes sense to say which is
worse or better of course.

Yevgen
 
R

Richard Eich

(e-mail address removed) wrote...
I think it would help if you could give us just a bit of context, at least.

Of course. Sorry.

iphp is a pointer to an IPv4 header. Specifically, it holds the
address of a populated IPv4 header ('iph' below).

sum is a long. It holds checksum calculation for the IPv4 header.

....
struct ip_hdr * iphp = &iph ;
int i, hlc = sizeof(iph) ;
long sum ;

for ( i = 0, sum = 0; hlc > 1; i++ )
{
sum += *((unsigned short *)iphp)++ ;
if ( sum & 0x80000000 )
sum = (sum & 0xFFFF) + (sum >>16) ;
hlc -= 2 ;
}
iph.ip_sum = htons( (short)~sum ) ;
....

I've been out sick, and am just now reading the responses to this
thread (which I thank the responders for).

Seems like the problem is the cast. I'm sure at least one of the
responses explains why. To me, it's done to make sure I'm adding to
sum only short-sized values and I'm utterly clueless as to why the
compiler wouldn't allow it.

Let me get through the responses though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top