旧 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;
可以编译源代码,但应用程序无法按预期工作。转化是真的吗?
【问题讨论】:
什么是u32
、u8
、hwrcolor
?
“应用程序无法按预期工作”,究竟出了什么问题?
@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++ 中