简体   繁体   中英

lvalue required as increment operand error with old C code

I get lvalue required as increment operand error message with gcc-4.7 for

void func1()
{
    u32 *src;
    hwrcolor c;

    c = *(((u32*)src)++);
}

and

void func2()
{
    u8 *dest;
    hwrcolor c;
    u32 * u32Dest;

    *(((u32 *)dest)++) = c;
}

I change them to

void func1()
{
    u32 *src;
    hwrcolor c;

    u32Dest = ((u32*)src);
    //c = *(u32Dest ++);
    *u32Dest = *u32Dest + 1;
    c = *u32Dest;
}

and

void func2()
{
    u8 *dest;
    hwrcolor c;
    u32 * u32Dest;

    u32Dest = ((u32 *)dest);
    //*(u32Dest++) = c;
    *u32Dest = *u32Dest + 1;
    *u32Dest = c;
}

source code can be compiled but application not work as expected. Are conversions true?

The code:

((T *)p)++

is illegal because ++ may only be applied to an lvalue.

This is because the side-effect of ++ is to increment the value stored in a variable, but (T *)p isn't a variable; it's a temporary result of converting p to a new type.

This is the same sort of error as int x = 5; (x + 3)++; int x = 5; (x + 3)++; . It doesn't make sense.

In some older compilers, the code ((T *)p)++; was accepted and treated like:

(*(T **)&p)++;

In other words, the memory location storing p was treated as if it actually stored a pointer of another type, and then that pointer is incremented. This worked on those compilers because those compilers only ran on hardware where all pointers are stored in the same way.


The fix for your func1 is simply to write c = *src++; . No casts are necessary because src is already the right type.

In func2 the code *(((u32 *)dest)++) = c; could be replaced with:

*(*(u32 **)&dest)++ = c;

Your version doesn't work because you never increment the original dest . In fact in both of your attempts you increment the data being pointed to, whereas the original code increments the pointer, leaving the data untouched.

Note that func2 violates the strict aliasing rule. Older compilers did not optimize based on the strict aliasing rule, but recent versions of gcc do. You should use the flag -fno-strict-aliasing when compiling this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM