类型转换:在C中将有符号整型转换为无符号长整型

6

我目前正在阅读《C程序设计语言》(K&R)的第二章,并学习位运算。

这是引起我的好奇心的例子:

x = x & ~077

假设字长为16位,长整型为32位,我认为将077转换为以下内容:
0000 0000 0011 1111 (16 bit signed int).

这将被补充为:
1111 1111 1100 0000.

我的问题是,对于不同可能的x类型,下一步会发生什么?如果x是有符号整数,则答案很简单。但是,如果x是带符号长整型,我认为~077将变为:

1111 1111 1111 1111 1111 1111 1100 0000

使用2的补码来保留符号。这样做正确吗?

另外,如果x是一个无符号长整型,那么~077会变成什么:

0000 0000 0000 0000 1111 1111 1100 0000

或者,是否先将~077转换为有符号长整型:
1111 1111 1111 1111 1111 1111 1100 0000

在此之后,它会被转换为无符号长整型(位数没有变化)吗?

任何帮助都可以帮助我澄清这个操作是否总是只将最后6位设置为零。


1
您可以通过使用调试器查看值或自己打印值来进行此测试。您还可以查看C语言规范。找出您的编译器所实现的规范,然后在相应的规范中查找详细信息。 "整数提升"可能是您要查找的内容。顺便说一句,在C语言中,我认为整数提升不应更改值。因此,您可能会得到一个符号扩展的值。 - rliu
2个回答

4
无论选择哪种数据类型,~077都会将最右边的6位设置为0,其余设置为1
假设使用16位的int和32位的long,有4种情况:
情况1
unsigned int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
unsigned long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000

案例二

unsigned int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
long y = ~x; // y = 0000 0000 0000 0000 1111 1111 1100 0000

案例三

int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
unsigned long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000

案例四

int x = 077; // x = 0000 0000 0011 1111
x = ~x; // x = 1111 1111 1100 0000
long y = ~x; // y = 1111 1111 1111 1111 1111 1111 1100 0000

请查看 这里的代码。这意味着当源码是signed时,会进行符号扩展。当源码是unsigned时,符号位不被扩展,左侧的位被设置为0


但是如果 ~077 是一个有符号整数,然后与无符号长整型进行 AND 操作会发生什么? - SpruceMoose
int x = 077; x = ~x; unsigned long y = x; 那么y是多少? - SpruceMoose
好的,我想我明白了。但是,在从有符号转换为无符号时进行符号扩展的意义何在,例如情况3?您知道我可以在哪里找到实际的C规范吗? - SpruceMoose
1
在谷歌上搜索后找到了这个链接,希望能对你有所帮助 :)另外,从这里得知:当将带有负号的整数提升为相同或更大类型的无符号整数时,它首先被提升为较大类型的有符号等效值,然后转换为无符号值。 - Sufian Latif

2
 x = x & ~077    //~077=11111111111111111111111111000000(not in every case)

~077 是一个在编译时计算出的常量,因此它的值将根据编译时 x 的值进行转换,因此 AND 操作将始终将 x 的最后 6 位转换为 0,并且剩余的位将保留其 AND 操作之前的值。就像这样:

//let x=256472--> Binary--> 0000 0000 0000 0011 1110 1001 1101 1000
 x = x & ~077;
// now x = 0000 0000 0000 0011 1110 1001 1100 0000 Decimal--> 256448

在编译期间,无论数据类型如何,最后6位都将被更改为0,剩余的位数保持不变。在knr中写道:

可移植形式不涉及任何额外费用,因为~077是一个可以在编译时求值的常量表达式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接