假设我有一个4字节的整数,我想将其转换为2字节的短整数。在小端和大端中,这个短整数将由这个4字节整数的两个最低有效字节组成,这样理解正确吗?
第二个问题:
在小端和大端处理器中,这段代码的结果会是什么?
int i = some_number;
short s = *(short*)&i;
在我看来,在大端处理器中,将复制两个最高有效字节,在小端处理器中,将复制两个最低有效字节。
假设我有一个4字节的整数,我想将其转换为2字节的短整数。在小端和大端中,这个短整数将由这个4字节整数的两个最低有效字节组成,这样理解正确吗?
第二个问题:
在小端和大端处理器中,这段代码的结果会是什么?
int i = some_number;
short s = *(short*)&i;
在我看来,在大端处理器中,将复制两个最高有效字节,在小端处理器中,将复制两个最低有效字节。
我是否正确,短整型将由这个4字节整数的2个最低有效字节组成?
是的,根据定义。
bigE和littleE的区别在于最低有效字节是否在最低地址。在little endian处理器中,最低地址是最不重要的位,x86就是这样做的。
在little E上,它们会得到相同的结果。
short s = (short)i;
short s = *(short*)&i;
在大端处理器上,最高地址是最不重要的位,例如68000和Power PC采用这种方式(实际上,Power PC可以是两种类型,但苹果的PPC机器使用bigE)。
对于big E,它们给出相同的结果。
short s = (short)i;
short s = ((short*)&i)[1]; // (assuming i is 4 byte int)
正如你所看到的,小端字节序允许您获取操作数最低有效位,而无需知道它有多大。小端字节序对于保持向后兼容性具有优势。
那么大端字节序有什么优点呢?它创建的十六进制转储更易于阅读。
实际上,摩托罗拉的工程师认为减轻读取十六进制转储的负担比向后兼容性更重要。英特尔的工程师则持相反观点。
是的。当你转换数值时,你不必担心字节序问题。
是的。当你转换指针时,你需要考虑字节序问题。
你应该意识到你的第二个例子
int i = some_number;
short s = *(short*)&i;
这不是有效的C代码,因为它违反了严格别名规则。在某些优化级别和/或编译器下,它很可能会失败。
使用联合体来解决这个问题:
union {
int i;
short s;
} my_union;
my_union.i = some_number;
printf("%d\n",my_union.s);
另外,正如其他人所指出的那样,您不能假设您的整数将是4个字节。在需要特定大小时最好使用int32_t和int16_t。
首先,您可能已经知道,但让我提一下,int 的大小不能保证为 4 个字节,short 的大小在所有平台上都是 2 个字节。
如果您的第一个问题意思是这样的:
int i = ...;
short s = (short)i;
是的,s
将包含 i
的低字节。
我认为对于你的第二个问题,答案也是肯定的;在字节级别上,系统的字节序确实会发挥作用。
short int_to_short(int n) {
if (n < SHRT_MIN) return SHRT_MIN;
if (n > SHRT_MAX) return SHRT_MAX;
return (short)n;
}
你甚至不必担心字节序问题,这门语言会为你处理好。如果你确定 n 在 short 类型的范围内,那么也可以跳过检查。