1

为什么这段代码没有结果y == 0x100

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

在这里自己检查一下:http: //codepad.org/dmsmrtsg

4

4 回答 4

9

从 C 语言的角度来看,您发布的代码是无效的。C 中任何强制转换的结果都是右值。它不能用作 的参数++。运算符++需要一个左值参数。ie 表达式++((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;

最终值为xwill 0

这正是您的示例中发生的情况。在 GCC 你的

++((unsigned) x)

相当于

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

这反过来又被 GCC 解释为

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

这就是为什么你作为结果0进入x的原因,这就是0然后被分配给你的y.

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

于 2012-10-11T14:26:10.670 回答
1

首先,这不是有效的 C 代码,我不知道您是如何编译它的,但是您的链接确实显示了输出,因此我将尝试根据这一主要假设来解释发生了什么:


我猜这行代码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

我们正在递增x( x=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)

于 2012-10-11T14:34:20.250 回答
0

试试这个:

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

它会如你所料,因为(unsigned) x现在是两字节0x0100

现在试试这个:

uint8_t x = 0xff;
++x;

的值0xff 环绕0x00

于 2012-10-11T14:34:42.107 回答
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:“从其块中获取我拥有的这些数据,将其在内存中的大小增加(或减少)到我想要将其转换为的大小,然后返回新块中的相同数据。

从我们的尺寸来看,unsigned将有足够的空间来适应单字节操作的计算结果。

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

x               = 11111111                         = 0xff  (in a byte)
(unsigned)x     = 00000000000000000000000011111111 = 0xff  (in a word)
++((unsigned)x) = 00000000000000000000000100000000 = 0x100
于 2012-10-11T14:54:32.800 回答