++((unsigned)x)的意外结果,x是uint8_t?

时间:2012-10-11 14:22:22

标签: c gcc

为什么这段代码不会导致y == 0x100

uint8_t x = 0xff;
unsigned y = ++((unsigned)x);

请在此处查看:http://codepad.org/dmsmrtsg

4 个答案:

答案 0 :(得分:9)

您发布的代码在C语言的观点上无效。 C中任何强制转换的结果都是右值。它不能用作++的参数。运算符++需要左值参数。即表达式++((unsigned) x)在标准C语言中是不可编译的。

在这种情况下,您实际观察到的是GCC的“广义左值”扩展

http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Lvalues.html

根据该扩展(与标准C相反),应用于左值的强制转换产生左值。当您尝试将某些内容写入结果“广义”左值时,正在写入的值将转换为两次:首先将其转换为显式强制转换所指定的类型,然后再次转换中间结果到收件人对象的类型。最终结果将放入收件人对象中。

例如,如果您使用x

(unsigned) x = 0x100;

它实际上将由GCC解释为

x = (uint8_t) (unsigned) 0x100;

x的最终值为0

这正是你的例子中发生的事情。在GCC你的

++((unsigned) x)

相当于

(unsigned) x = (unsigned) x + 1;

又由GCC解释为

x = (uint8_t) (unsigned) ((unsigned) x + 1);

这就是您在0中获得x作为结果的原因,那就是0然后被分配给您的y

此扩展程序被GCC文档称为已弃用

答案 1 :(得分:1)

要开始这不是有效的C代码,我不知道你是如何编译的,但是你的链接确实显示了一个输出,所以我将尝试根据这个 major <来解释发生了什么/ strong>假设:


我想使用这一行unsigned y = ++((unsigned x));,你的编译器会删除第二个unsigned,因此你可以构建它。


所以,假设......

uint8_t x = 0xff;    // 8 bit value, max is 255(10) or 0xFF(16)
unsigned y = ++((unsigned)x); 

现在x已经为其类型提供了最大值。您想知道为什么如果我们通过++ +1,y没有获得0x100的值。

x是8位,类型转换它并没有改变它是8位的事实。所以当我们说:

++x

我们正在递增xx=x+1)。所以我们有一个无符号的8位值,最大值并加1,现在它被包围到0.所以y将得到0.

如果你想要这个,你可以做类似的事情:

int main(void) 
{
    unsigned char x = 0xFF; //I'm using char because it's 8 bit too
    unsigned int y = 1+x;   //no need to typecast, we're already unsigned
    printf("%#x %#x\n", x, y);
    return 0; 
} 

现在,您将获得预期值(x==0xFFy==0x100

答案 2 :(得分:0)

试试这个:

uint8_t x = 0xff;
unsigned y = ((unsigned)x) + 1;

它会按照您的预期出现,因为(unsigned) x现在是双字节0x0100

现在试试这个:

uint8_t x = 0xff;
++x;

0xff 的值包围0x00

答案 3 :(得分:0)

我在您的摘录中添加了一些透明度代码,它解释了所有内容。

#include <stdio.h>
#include <stdint.h> // not needed

int main(void) {
  uint8_t x = 0xff;
  printf("%d\n", sizeof(x));
  unsigned y = ++((unsigned)x); 
  printf("%d\n", sizeof(y));
  printf("0x%x\n", y);
  printf("%d\n", sizeof(y));
  return 0;
}

,输出

1      // size of x
4      // size of y before computation
0x100  // computed value of y from your code
4      // size of y after computation

首先要注意的是sizeof(y)在计算中保持不变 从输出中,

  • uint8_t = 1个字节
  • unsigned = 4个字节

当你在C中进行强制转换时,将其视为对realloc的隐式调用,其中说:“从块中获取此数据,将其在内存中的大小增加(或减少)到大小为I想要将其转换为,然后在新块中返回相同的数据。

根据我们的大小,unsigned将有足够的空间来容纳来自单字节操作的计算结果。

以字节级细节重新解释您的代码,

x               = 11111111                         = 0xff  (in a byte)
(unsigned)x     = 00000000000000000000000011111111 = 0xff  (in a word)
++((unsigned)x) = 00000000000000000000000100000000 = 0x100