C 无符号整型数组和位移位

发布于 2024-08-11 15:05:30 字数 110 浏览 9 评论 0原文

如果我有一个短无符号整数数组。

将 array[k+1] 左移 8 位,将 8 位放入 array[k+1] 的下半部分?

或者它们是否只是因为超出了为元素分配的空间而掉落?

If i have an array of short unsigned ints.

Would shifting array[k+1] left by 8 bits, put 8 bits into the lower half of array[k+1]?

Or do they simply drop off as they have gone outside of the allocated space for the element?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

撕心裂肺的伤痛 2024-08-18 15:05:30

他们下车了。您不能以这种方式影响其他位。尝试一下:

#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

They drop off. You can't affect the other bits this way. Try it:

#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;
}

Output is

0:1
1:FFFFFFFF
2:3
0:1
1:FFFFFF00
2:3
李白 2024-08-18 15:05:30

它们完全放弃数据类型,而不保留到下一个数组元素。

如果您想要这种行为,您必须自己编写类似的代码(将整个数组左移四位):

#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

They drop off the data type totally, not carrying over to the next array element.

If you want that sort of behavior, you have to code it yourself with something like (left shifting the entire array by four bits):

#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;
}

This outputs:

before 0: 0xdead
before 1: 0x1234
before 2: 0x5678
before 3: 0xbeef

after  0: 0xad12
after  1: 0x3456
after  2: 0x78be
after  3: 0xef00
御弟哥哥 2024-08-18 15:05:30

考虑这个问题的方法是,在 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 中,对其进行修改,然后将其存储回来。

The way to think about this is that in C (and for most programming languages) the implementation for array[k] << 8 involves loading array[k] into a register, shifting the register, and then storing the register back into array[k]. Thus array[k+1] will remain untouched.

As an example, foo.c:

unsigned short array[5];

void main() {
  array[3] <<= 8;
}

Will generate the following instructions:

movzwl  array+6(%rip), %eax
sall    $8, %eax
movw    %ax, array+6(%rip)

This loads array[3] into %eax, modifies it, and stores it back.

路弥 2024-08-18 15:05:30

将无符号整型左移 8 位将用零填充低 8 位。前 8 位将被丢弃,无论它们是否在数组中。

顺便说一句,8 位是否是 unsigned int 的一半取决于您的系统,但在 32 位系统上,8 位通常是 unsigned int 的四分之一。

unsigned int x = 0x12345678;
// x is 0x12345678

x <<= 8;
// x is 0x34567800

Shifting an unsigned int left by 8 bits will fill the lower 8 bits with zeros. The top 8 bits will be discarded, it doesn't matter that they are in an array.

Incidentally, whether 8 bits is half of an unsigned int depends on your system, but on 32-bit systems, 8 bits is typically a quarter of an unsigned int.

unsigned int x = 0x12345678;
// x is 0x12345678

x <<= 8;
// x is 0x34567800
一城柳絮吹成雪 2024-08-18 15:05:30

请注意,int 数据类型的 C 定义未指定它包含多少位,并且与系统相关。 int 最初旨在成为处理器的“自然”字大小,但情况并非总是如此,您可能会发现 int 包含 16、32、64 甚至某些奇数(例如 24 位)。

唯一可以保证的是 unsigned int 可以保存 0 到 UINT_MAX 之间的所有值(包括 0 和 UINT_MAX),其中 UINT_MAX 必须至少为 65535 - 因此 int 类型必须包含至少 16 位才能保存所需的值范围。

因此,将整数数组移位 8 位将分别更改每个 int,但请注意,此移位不一定是“数组的一半”

Be aware that the C definition of the int data type does not specify how many bits it contains and is system dependent. An int was originally intended to be the "natural" word size of the processor, but this isn't always so and you could find int contains 16, 32, 64 or even some odd number like 24 bits.

The only thing you are guaranteed is an unsigned int can hold all the values between 0 and UINT_MAX inclusive, where UINT_MAX must be at least 65535 - so the int types must contain at least 16 bits to hold the required range of values.

So shifting an array of integer by 8 bits will change each int individually, but be aware that this shift will not necessarily be 'half of the array'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文