C 意外的++;((未签名)x),x是uint8_t?
为什么这段代码不会导致C 意外的++;((未签名)x),x是uint8_t?,c,gcc,C,Gcc,为什么这段代码不会导致y==0x100 uint8_t x = 0xff; unsigned y = ++((unsigned)x); 请在此处亲自查看:从C语言的角度来看,您发布的代码是无效的。C中任何强制转换的结果都是右值。它不能用作++的参数。运算符++需要左值参数。也就是说,表达式++((无符号)x)在标准C语言中是不可编译的 在本例中,您实际观察到的是GCC的“广义左值”扩展 根据该扩展(与标准C相反),应用于左值的转换生成左值。当您尝试将某些内容写入结果“广义”左值时,所写入的值
y==0x100
uint8_t x = 0xff;
unsigned y = ++((unsigned)x);
请在此处亲自查看:从C语言的角度来看,您发布的代码是无效的。C中任何强制转换的结果都是右值。它不能用作
++
的参数。运算符++
需要左值参数。也就是说,表达式++((无符号)x)
在标准C语言中是不可编译的
在本例中,您实际观察到的是GCC的“广义左值”扩展
根据该扩展(与标准C相反),应用于左值的转换生成左值。当您尝试将某些内容写入结果“广义”左值时,所写入的值将被转换两次:首先将其转换为显式转换指定的类型,然后将中间结果再次转换为接收方对象的类型。最终结果将放入收件人对象中
例如,如果使用x
您可以
(unsigned) x = 0x100;
GCC实际上会将其解释为
x = (uint8_t) (unsigned) 0x100;
x = (uint8_t) (unsigned) ((unsigned) x + 1);
x
的最终值将为0
这就是你的例子中发生的事情。在你的
++((unsigned) x)
相当于
(unsigned) x = (unsigned) x + 1;
GCC将其解释为:
x = (uint8_t) (unsigned) 0x100;
x = (uint8_t) (unsigned) ((unsigned) x + 1);
这就是为什么在x
中得到0
作为结果,这就是0
然后分配给y
的原因
GCC文档称此扩展已弃用。从C语言的角度来看,您发布的代码无效。C中任何强制转换的结果都是右值。它不能用作
++
的参数。运算符++
需要左值参数。也就是说,表达式++((无符号)x)
在标准C语言中是不可编译的
在本例中,您实际观察到的是GCC的“广义左值”扩展
根据该扩展(与标准C相反),应用于左值的转换生成左值。当您尝试将某些内容写入结果“广义”左值时,所写入的值将被转换两次:首先将其转换为显式转换指定的类型,然后将中间结果再次转换为接收方对象的类型。最终结果将放入收件人对象中
例如,如果使用x
您可以
(unsigned) x = 0x100;
GCC实际上会将其解释为
x = (uint8_t) (unsigned) 0x100;
x = (uint8_t) (unsigned) ((unsigned) x + 1);
x
的最终值将为0
这就是你的例子中发生的事情。在你的
++((unsigned) x)
相当于
(unsigned) x = (unsigned) x + 1;
GCC将其解释为:
x = (uint8_t) (unsigned) 0x100;
x = (uint8_t) (unsigned) ((unsigned) x + 1);
这就是为什么在x
中得到0
作为结果,这就是0
然后分配给y
的原因
GCC文档将此扩展称为不推荐使用的扩展。首先,这是无效的C代码,我不知道您是如何编译它的,但您的链接确实显示了一个输出,因此我将尝试根据这一假设解释发生了什么
我猜这一行
无符号y=++((无符号x))代码>编译器正在删除第二个未签名的
,因此您可以构建
所以,假设
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==0xFF
和y==0x100
)开始这是无效的C代码,我不知道您是如何编译它的,但您的链接确实显示了一个输出,因此我将尝试根据这一假设解释发生了什么:
我猜这一行无符号y=++((无符号x))代码>编译器正在删除第二个未签名的
,因此您可以构建
所以,假设
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==0xFF
和y==0x100
)尝试以下方法:
uint8_t x = 0xff;
unsigned y = ((unsigned)x) + 1;
它的结果将与您预期的一样,因为(unsigned)x
现在是两个字节的值0x0100
现在试试这个:
uint8_t x = 0xff;
++x;
0xff
的值环绕到0x00
尝试以下操作:
uint8_t x = 0xff;
unsigned y = ((unsigned)x) + 1;
它的结果将与您预期的一样,因为(unsigned)x
现在是两个字节的值0x0100
现在试试这个:
uint8_t x = 0xff;
++x;
0xff
的值是0x00
我在你的摘录中加入了一些透明代码,它解释了一切
#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;
}
首先要注意的是,sizeof(y)
在整个计算过程中保持不变。
从产出来看
uint8\u t
=1字节
无符号
=4字节
在C中执行强制转换时,可以将其视为对realloc
的隐式调用,其中说:“从其块中获取此数据,将其在内存中的大小增加(或减少)到我想要的大小