如果我有一个短无符号整数数组。
将 array[k+1] 左移 8 位,将 8 位放入 array[k+1] 的下半部分?
或者他们只是因为超出了为元素分配的空间而放弃了?
他们下车。你不能以这种方式影响其他位。尝试一下:
#include <stdio.h>
void print_a (short * a)
{
int i;
for (i = 0; i < 3; i++)
printf ("%d:%X\n", i, a[i]);
}
int main ()
{
short a[3] = {1, -1, 3};
print_a (a);
a[1] <<= 8;
print_a (a);
return 0;
}
输出是
0:1 1:FFFFFFFF 2:3 0:1 1:FFFFFF00 2:3
他们完全放弃了数据类型,而不是延续到下一个数组元素。
如果你想要这种行为,你必须自己编写代码(将整个数组左移四位):
#include <stdio.h>
int main(void) {
int i;
unsigned short int a[4] = {0xdead,0x1234,0x5678,0xbeef};
// Output "before" variables.
for (i = 0; i < sizeof(a)/sizeof(*a); i++)
printf ("before %d: 0x%04x\n", i, a[i]);
printf ("\n");
// This left-shifts the array by left-shifting the current
// element and bringing in the top bit of the next element.
// It is in a loop for all but hte last element.
// Then it just left-shifts the last element (no more data
// to shift into that one).
for (i = 0; i < sizeof(a)/sizeof(*a)-1; i++)
a[i] = (a[i] << 8) | (a[i+1] >> 8);
a[i] = (a[i] << 8);
// Print the "after" variables.
for (i = 0; i < sizeof(a)/sizeof(*a); i++)
printf ("after %d: 0x%04x\n", i, a[i]);
return 0;
}
这输出:
before 0: 0xdead
before 1: 0x1234
before 2: 0x5678
before 3: 0xbeef
after 0: 0xad12
after 1: 0x3456
after 2: 0x78be
after 3: 0xef00
考虑这一点的方法是,在 C(以及大多数编程语言)中,实现array[k] << 8
涉及将 array[k] 加载到寄存器中,移位寄存器,然后将寄存器存储回 array[k]。因此 array[k+1] 将保持不变。
例如,foo.c
:
unsigned short array[5];
void main() {
array[3] <<= 8;
}
将生成以下指令:
movzwl array+6(%rip), %eax
sall $8, %eax
movw %ax, array+6(%rip)
这会将 array[3] 加载到 %eax 中,对其进行修改,然后将其存储回来。
将 unsigned int 左移 8 位将用零填充低 8 位。前 8 位将被丢弃,它们是否在数组中并不重要。
顺便说一句,8 位是否是 unsigned int 的一半取决于您的系统,但在 32 位系统上,8 位通常是 unsigned int 的四分之一。
unsigned int x = 0x12345678;
// x is 0x12345678
x <<= 8;
// x is 0x34567800
请注意,int 数据类型的 C 定义没有指定它包含多少位,并且取决于系统。int 最初旨在成为处理器的“自然”字长,但并非总是如此,您可能会发现 int 包含 16、32、64 甚至一些奇数,如 24 位。
唯一可以保证的是 unsigned int 可以保存 0 到 UINT_MAX 之间的所有值,其中 UINT_MAX 必须至少为 65535 - 因此 int 类型必须包含至少 16 位以保存所需的值范围。
因此,将整数数组移位 8 位将单独更改每个 int,但请注意,这种移位不一定是“数组的一半”