Bol*_*boa 36 c casting truncate
有人可以澄清当一个整数被转换为shortC 时会发生什么吗?我正在使用Raspberry Pi,所以我知道a int是32位,因此short必须是16位.
假设我使用以下C代码作为示例:
int x = 0x1248642;
short sx = (short)x;
int y = sx;
Run Code Online (Sandbox Code Playgroud)
我知道这x会被截断,但有人可以解释一下究竟是怎么回事?轮班使用了吗?数字究竟是如何从32位截断到16位的?
Kei*_*son 39
根据ISO C标准,当您将整数转换为有符号类型,并且该值超出目标类型的范围时,结果是实现定义的.(或者可以引发实现定义的信号,但我不知道有任何编译器执行此操作.)
实际上,最常见的行为是丢弃高位.假设int是32位且short是16位,转换该值0x1248642可能会产生一个看起来像的位模式0x8642.假设有符号类型的二进制补码表示(几乎在所有系统上都使用),高位是符号位,因此结果的数值将是-31166.
int y = sx;
Run Code Online (Sandbox Code Playgroud)
这也涉及到的隐式转换,从short到int.由于int保证范围至少涵盖整个范围short,因此该值不变.(因为,在您的示例中,值sx恰好为负值,此表示更改可能涉及符号扩展,将1符号位传播到结果的所有16个高位.)
正如我所指出的那样,语言标准不需要这些细节.如果你真的想要将值截断为更窄的类型,那么最好使用无符号类型(具有语言指定的环绕行为)以及可能的显式屏蔽操作,如下所示:
unsigned int x = 0x1248642;
unsigned short sx = x & 0xFFFF;
Run Code Online (Sandbox Code Playgroud)
如果你要推到一个16位变量32位的数量,你应该做的第一件事就是决定如何你想你的代码的行为,如果该值不适合.一旦你决定了,你就可以弄清楚如何编写符合你想要的C代码.有时截断恰好是您想要的,在这种情况下,您的任务将很容易,特别是如果您使用的是无符号类型.有时超出范围的值是错误,在这种情况下,您需要检查它并决定如何处理错误.有时您可能希望值饱和而不是截断,因此您需要编写代码来执行此操作.
了解转换在C中的工作方式非常重要,但如果从问题开始,您可能会从错误的方向接近您的问题.
Ami*_*mit 12
32位值被截断为16位,如果将其塞入16厘米长的平底锅中,则会切割32厘米长的香蕉面包.其中一半适合并仍然是香蕉面包,其余的将"消失".
截断发生在CPU寄存器中.它们有不同的大小:8/16/32/64位.现在,您可以想象一个寄存器,如:
<--rax----------------------------------------------------------------> (64-bit)
<--eax----------------------------> (32-bit)
<--ax-----------> (16-bit)
<--ah--> <--al--> (8-bit high & low)
01100011 01100001 01110010 01110010 01111001 00100000 01101111 01101110
Run Code Online (Sandbox Code Playgroud)
x首先给出32位值0x1248642.在内存*中,它看起来像:
-----------------------------
| 01 | 24 | 86 | 42 |
-----------------------------
31..24 23..16 15..8 7..0
Run Code Online (Sandbox Code Playgroud)
现在,编译器加载x到寄存器中.从它,它可以简单地加载最低有效16位(即,ax)并存储它们sx.
*为简单起见,不考虑字节序
只需从整数中切除高16位即可。因此,您的空头将变为0x8642实际上为负数-31166。
也许让代码说明一切:
#include <stdio.h>
#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d"
#define BYTETOBINARY(byte) \
((byte) & 0x80 ? 1 : 0), \
((byte) & 0x40 ? 1 : 0), \
((byte) & 0x20 ? 1 : 0), \
((byte) & 0x10 ? 1 : 0), \
((byte) & 0x08 ? 1 : 0), \
((byte) & 0x04 ? 1 : 0), \
((byte) & 0x02 ? 1 : 0), \
((byte) & 0x01 ? 1 : 0)
int main()
{
int x = 0x1248642;
short sx = (short) x;
int y = sx;
printf("%d\n", x);
printf("%hu\n", sx);
printf("%d\n", y);
printf("x: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(x>>24), BYTETOBINARY(x>>16), BYTETOBINARY(x>>8), BYTETOBINARY(x));
printf("sx: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(y>>8), BYTETOBINARY(y));
printf("y: "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN" "BYTETOBINARYPATTERN"\n",
BYTETOBINARY(y>>24), BYTETOBINARY(y>>16), BYTETOBINARY(y>>8), BYTETOBINARY(y));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
19170882
34370
-31166
x: 00000001 00100100 10000110 01000010
sx: 10000110 01000010
y: 11111111 11111111 10000110 01000010
Run Code Online (Sandbox Code Playgroud)
如您所见,int-> short产生了低16位,与预期的一样。
强制转换short为int产生short16位高位的。但是,我怀疑这是特定于实现且未定义的行为。您实际上是将16位内存解释为一个整数,它会读取垃圾中可能出现的16位多余的位(如果编译器很好,并且希望帮助您更快地发现错误,则读取1位)。
我认为执行以下操作应该是安全的:
int y = 0x0000FFFF & sx;
Run Code Online (Sandbox Code Playgroud)
显然,您不会找回丢失的位,但这将确保高位正确归零。
如果任何人都可以通过权威参考来验证short-> int high bit行为,将不胜感激。
注意:二进制宏改编自此答案。
| 归档时间: |
|
| 查看次数: |
25143 次 |
| 最近记录: |