【问题标题】:removing left shift count >= width of type warning删除左移计数> =类型警告的宽度
【发布时间】:2016-09-21 03:57:48
【问题描述】:

为什么这段代码会产生警告:

niko: snippets $ cat leftshift.c 
#include <stdint.h>
#include <stdio.h>

int main(void) {

    uint32_t var1;
    uint32_t var2;

    var1=55;
    var2=var1 << (sizeof(uint32_t)-8);

    printf("%d\n",var2);
}
niko: snippets $ gcc -g -Wl,--warn-common -ffunction-sections -fshort-enums -fdata-sections -Wall -Wextra -Wunreachable-code -Wmissing-prototypes -Wmissing-declarations -Wunused -Winline -Wstrict-prototypes -Wimplicit-function-declaration -Wformat  -D_GNU_SOURCE -fshort-enums -std=c99  -c leftshift.c 
leftshift.c: In function ‘main’:
leftshift.c:10:12: warning: left shift count >= width of type [-Wshift-count-overflow]
  var2=var1 << (sizeof(uint32_t)-8);
            ^
niko: snippets $ 

虽然相同的代码没有:

niko: snippets $ cat leftshift.c 
#include <stdint.h>
#include <stdio.h>

int main(void) {

    uint32_t var1;
    uint32_t var2;

    var1=55;
    var2=var1 << (32-8);

    printf("%d\n",var2);
}
niko: snippets $ gcc -g -Wl,--warn-common -ffunction-sections -fshort-enums -fdata-sections -Wall -Wextra -Wunreachable-code -Wmissing-prototypes -Wmissing-declarations -Wunused -Winline -Wstrict-prototypes -Wimplicit-function-declaration -Wformat  -D_GNU_SOURCE -fshort-enums -std=c99  -c leftshift.c 
niko: snippets $ 

GCC 有什么问题吗?因为 uint32_t 的大小是 32 位还是不是?

【问题讨论】:

    标签: c


    【解决方案1】:

    Sizeof 以字节为单位返回大小。你应该试试这个:

    printf("%d\n", sizeof(uint32_t));
    

    您可能会发现它是 4,而不是 32。如果您想要以位为单位的大小,可以乘以 8:sizeof(uint32_t) * 8

    【讨论】:

    • 请注意,%dsize_t 的错误类型说明符,sizeof 返回。请改用%zu,或将参数转换为与类型说明符匹配的类型。
    • sizeof(uint32_t) * CHAR_BIT 更便于携带和自我记录。 OTOH CHAR_BIT == 8 很常见。
    【解决方案2】:

    sizeof(uint32_t) 在您的系统中为 4,因此第一个代码将正确的操作数设为 (4-8),这是一个负数,因此会发出警告。

    在第二个代码中它是一个正数,所以没有警告。

    【讨论】:

    • sizeof(uint32_t)size_t 类型,所以 sizeof(uint32_t)-8 会产生一个非常大的无符号数。这就是为什么“左移计数>=类型宽度”
    • 按位运算符的右侧是加法表达式(c11 的 6.5.7)。它可以是负数,但如果它是负数,则结果是不确定的。因此,整数提升将发生在 sizeof(uint32_t) 上,它将变为有符号整数,结果将是有符号整数。移位表达式的结果将是未定义的。
    • 如果sizeof(size_t) &lt; sizeof(int),那么减法的结果将是负符号整数。如果sizeof(size_t) &gt;= sizeof(int),则结果是大的无符号整数。无论哪种方式,结果都超出了右位移操作数 (0 .. 31) 的允许范围,并且行为未定义。
    • @user694733 sizeof(size_t) - sizeof(int) 的结果是类型size_tsize_t 是一些无符号类型,而不是有符号整数。结果不能为负。
    • @chux 我不是这么说的。没有减法sizeof(size_t) - sizeof(int)。只有减法sizeof(uint32_t)-8 具有类型size_t - int。如果我们在sizeof(size_t) &lt; sizeof(int) 的机器上,那么在减法之前sizeof(uint32_t) 的结果会提升为int,然后减法结果可能是负数。现在考虑到 OP 收到的错误消息,这 不是 这样的机器,但这样的系统仍然可以存在。
    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-22
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多