Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Compilation error - invalid lvalue in assignment

Status
Not open for further replies.

sin888

IS-IT--Management
Jun 22, 2010
1
FI
Hi,

I've have been having issues lately trying to compile a code that use to compile nicely before the upgrade to GCC version 4.x.x

The code is here.

int recvtcp( char *buf, int sizeofbuffer)
{
int datalink;
struct pcap_pkthdr useless;

struct tcppacket
{
struct iphdr ip;
struct tcphdr tcp;
u_char *data;

} *tcppacket;

tcppacket = (struct tcppacket *) pcap_next (pcap_global_descriptor, &useless);
(char *) tcppacket += offset; <--- error while compiling

The error lies in (char *) tcppacket += offset;

Would be great if anyone of you could shed some light on this thanks. The programmer that did the program already left the company....Couldn't get in contact with him. Any help would be much appreciated.
 
One, what is the error message that you are receiving?

Two, there does not appear to be any definition of offset. Unless this is defined in a location that places it in scope, this will cause an error. In and of itself, this doesn't explain why it used to compile, but could be a clue as to what is going wrong.
 
It's because a cast returns an r-value, and you're using it as an l-value.

Various compilers' supported such things in one form or another, but it has never been a standard feature.

The way forward is
Code:
char *temp = (char *)tcppacket;
temp += offset;
tcppacket = (struct tcppacket*)temp;

But such code is highly dubious. If offset is anything other than a multiple of [tt]sizeof(struct tcppacket)[/tt], then you're going to end up with unaligned accesses.

And if it always is a multiple of the struct size, then you can simply do
Code:
tcppacket += offset / sizeof(struct tcppacket);



--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
@salem: My hat goes off to you in regards to your knowledge of C and GCC. I have been programming professionally for 15 years and had to look this one up.

According to the documentation I have found ( in C the result of the cast operation is not is not an lvalue. In C++ it is an lvalue IF the type being cast is a reference, otherwise it is an rvalue.

I assume that the source being compiled was C, not C++ and I admit that I have used this type of construct myself in previous applications, where it is desirable generate a byte offset into a structure.

It also looks like this feature may have been illegal as of C90 and deprecated. Is it now illegal?
 
Casts have never been l-values in C, even before ANSI created a standard for C.

> compile a code that use to compile nicely before the upgrade to GCC version 4.x.x
To me, this is just a compiler bug fix.

Unfortunately, most debugging stops as soon as the current compiler stops complaining and the resulting program stops crashing.

Performing any kind of upgrade is likely to flush out a few more problems. This is simply another example.


--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
Hi just thought I'd throw in a comment. I agree with "Norway2" in both points, but will assume that cast had been previously defined or I would expect any compiler to gag on it. BTW are you sure of the ACTUAL error line? I started programming in the mid 70's and some things are not what they seem.

My programming actually started as a 'B' programmer and a move to C on it's creation was immediate. As a retired Sr Prog/Analyst I see lots of code that mean big problems when porting to other systems. My first machine was a 6 bit byte!

I just wanted to point out that the inclusion of the error message itself, is critical, as is any previous warnings or errors. Also, when addressing anything it's usually the hardware that determines what is returned. C was created with that and speed in mind, so some things are left rather undefined as how they are implemented (on purpose), hence the most logical address is the size of the pointer, which is what you are dealing with. Sometimes a good clue is to get the compiler output, I.E. was it has done to your code, not just a listing but how it breaks down the (and re-writes your code for efficiency). This will usually tip you off to what's getting mangled in your code.

One other thing, if you are running for speed, byte offsets can generate a lot of object code that could be better handled by your coding method. I won't get into some compilers generating last variables first or vice-versa. I know that C leaves gives you lots of rope, enough to hang yourself, so if you need a specific offset, build that into the structure and the compiler will figure out the quickest path, usually even though next piece of hardware may work differently.

I started life as a hardware specialist then Hard/Soft specialist and then moved into teaching many languages from Ada, B, C, COBOL, SNOWBALL bit-slice software and assembler (Even IBM 370), just as a start. So I got to experience many variations in code generation and speed and some students thinking process!

I love C and still use it as my primary source, but every time a new compiler comes out, check the modified source from the compiler and the generated assembler. I mostly do architecture of systems now. Most are VERY LARGE. Just some general hints that have my life easier, hope they will help others.

Always keep in mind that when you step on one bug a bunch more come to the funeral.

Sorry the post was so long!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top