宏定义有什么区别:' #define my_macro(1 << 16) '和“#define my_macro(1U << 16)”

发布于 2024-11-24 08:05:30 字数 86 浏览 2 评论 0 原文

我可以猜测后者明确表示将“1”视为无符号整数。但如果是前者的话,有哪些不良副作用呢?我看到这两个都在 Linux 内核中使用。那么哪一个更准确/推荐,为什么?

I can guess that the latter explicitly indicates to treat the '1' as an unsigned integer. But what are the bad side-effects if any of the former. I see both of these being used in the linux kernel. So which one is the more accurate/recommended and why?

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

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

发布评论

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

评论(2

苍景流年 2024-12-01 08:05:30

1 << 的一个问题当您将 1 向左移动足够远时,x 就会变得明显。在具有整数补码表示的机器上,这会使该值突然变为负数。假设 int 宽度为 32 位:

#include <stdio.h>

int
main(int argc, const char** argv) 
{
    printf("%d\n", (1 << 30));
    printf("%d\n", (1 << 31));
    printf("%ud\n", (1U << 30));
    printf("%ud\n", (1U << 31));        
    return 0;
}

在我的机器上产生

1073741824
-2147483648
1073741824d
2147483648d

。这在代码的其他部分可能是意想不到的。特别是,由于反向移位不一定等效,由于有符号扩展:

#include <stdio.h>

int
main(int argc, const char** argv) 
{
    printf("%d\n", (2 << 29) >> 29);
    printf("%d\n", (2 << 30) >> 30);
    printf("%u\n", (2U << 29) >> 29);
    printf("%u\n", (2U << 30) >> 30);
    return 0;
}

产生

2
-2 
2 
2

注意他翻转了第二个输出行上的符号...

One problem with 1 << x becomes obvious, when you shift the 1 far enough to the left. On machines with twos-complement representation for integers, this makes the value suddenly become negative. Assuming an int width of 32 bits:

#include <stdio.h>

int
main(int argc, const char** argv) 
{
    printf("%d\n", (1 << 30));
    printf("%d\n", (1 << 31));
    printf("%ud\n", (1U << 30));
    printf("%ud\n", (1U << 31));        
    return 0;
}

yields

1073741824
-2147483648
1073741824d
2147483648d

on my machine. This might be unexpected in other parts of the code. In particular, as the reverse shift is not necessarily equivalent, due to signed-extension:

#include <stdio.h>

int
main(int argc, const char** argv) 
{
    printf("%d\n", (2 << 29) >> 29);
    printf("%d\n", (2 << 30) >> 30);
    printf("%u\n", (2U << 29) >> 29);
    printf("%u\n", (2U << 30) >> 30);
    return 0;
}

yields

2
-2 
2 
2

Notice he flipped sign on the second output line...

多像笑话 2024-12-01 08:05:30

这取决于您运行它的系统。
如果系统中整数为 16 位,则 (1 << 16) 将“超出边缘”,数字将为 0。在 32 位系统上,数字将为 2^16 (65536)。

由于移位是 16,因此 1 是否无符号并不重要。
但是,如果移位为 15,则情况会更复杂:

无符号 16 位整数在移位后的值为 2^15 (32768),而有符号 16 位整数的值为 -2^ 15 (-32768) 以二进制补码表示。

This depends on the system you are running this on.
If it's a system where integers are 16-bit then (1 << 16) would "go off the edge" and the number would be 0. On a 32-bit system the number would be 2^16 (65536).

Since the shift is 16 then it really doesn't matter if 1 is unsigned or not.
However if the shift were to be 15 then it is more complicated:

An unsigned 16-bit integer would, after the shift, have the value of 2^15 (32768) while a signed 16-bit integer would have the value -2^15 (-32768) in a twos-complement representation.

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