旧 C 代码中需要左值作为增量操作数错误

Posted

技术标签:

【中文标题】旧 C 代码中需要左值作为增量操作数错误【英文标题】:lvalue required as increment operand error with old C code 【发布时间】:2015-06-12 07:48:10 【问题描述】:

我使用 gcc-4.7 for 得到 lvalue 作为增量操作数错误消息

void func1()

    u32 *src;
    hwrcolor c;

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

void func2()

    u8 *dest;
    hwrcolor c;
    u32 * u32Dest;

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

我把它们改成

void func1()

    u32 *src;
    hwrcolor c;

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

void func2()

    u8 *dest;
    hwrcolor c;
    u32 * u32Dest;

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

可以编译源代码,但应用程序无法按预期工作。转化是真的吗?

【问题讨论】:

什么是u32u8hwrcolor “应用程序无法按预期工作”,究竟出了什么问题? @user4757345 包括强制转换在内的转换运算符将值转换为指定类型。所以即使这个代码 sn-p int x = 10;整数y; y = ( ( int )x )++;不会编译。 你应该研究一下*(p++);(*p)++;之间的区别。 【参考方案1】:

代码:

((T *)p)++

是非法的,因为++ 只能应用于左值。

这是因为++ 的副作用是增加存储在变量中的值,但(T *)p 不是变量;这是将p 转换为新类型的临时结果。

这与 int x = 5; (x + 3)++; 的错误类型相同。这没有意义。

在一些较旧的编译器中,代码 ((T *)p)++; 被接受并被视为:

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

换句话说,存储p 的内存位置被视为实际上存储了另一种类型的指针,然后该指针递增。这适用于那些编译器,因为这些编译器只在所有指针以相同方式存储的硬件上运行。


func1 的修复方法是简单地编写 c = *src++; 。不需要强制转换,因为 src 已经是正确的类型。

func2 中,代码*(((u32 *)dest)++) = c; 可以替换为:

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

您的版本不起作用,因为您从未增加原始dest。事实上,在您的两次尝试中,您都会递增指向的数据,而原始代码会递增指针,而不会触及数据。

请注意,func2 违反了严格的别名规则。较旧的编译器没有根据严格的别名规则进行优化,但最新版本的 gcc 可以。编译此代码时应使用标志-fno-strict-aliasing

【讨论】:

以上是关于旧 C 代码中需要左值作为增量操作数错误的主要内容,如果未能解决你的问题,请参考以下文章

无法理解 C 源代码,它不能在 GCC 中编译,但在 Visual C++ 中

需要作为增量运算符的左值 [重复]

关于 C++ 和 stl 向量的 begin() 的“需要左值作为增量操作数”

C 错误:需要左值作为一元“&”操作数

左值错误和数组指针

条件运算符中的“错误:需要左值作为赋值的左操作数”