我需要左值作为增量操作数错误消息,使用gcc-4.7
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;
}
源代码可以编译,但应用程序不能按预期工作。转换是真的吗?
答案 0 :(得分: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
。