lvalue需要作为旧C代码的增量操作数错误

时间:2015-06-12 07:48:11

标签: c

我需要左值作为增量操作数错误消息,使用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;
}

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

1 个答案:

答案 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