简体   繁体   English

编译器警告:负值左移

[英]compiler warning: left shift of negative value

I think GCC is wrongfully producing a [-Wshift-negative-value] warning.我认为 GCC 错误地产生了 [-Wshift-negative-value] 警告。

I have a function that should produce a suffix mask of a certain length provided by its single input argument:我有一个 function 应该产生一个由其单个输入参数提供的特定长度的后缀掩码:

#include <stdint.h>

uint16_t get_suffix_mask_sht(uint8_t shift) {
    return (~(~((uint16_t) 0) << shift));
}

I have tried to compile this function with the following compiler options on different versions of gcc我尝试在不同版本的 gcc 上使用以下编译器选项编译此 function

-Werror -Wextra

This warning also occurs if I change the output from uint16_t to uint8_t .如果我将 output 从uint16_t更改为uint8_t ,也会出现此警告。 Bigger output types, ie uint32_t don't produce this warning.更大的 output 类型,即uint32_t不会产生此警告。

I am using an older version of GCC: 7.4.我使用的是旧版本的 GCC:7.4。 But I have tried this out on godbolt using the latest GCC 9.x versions and they all produce the same warning.但是我已经使用最新的 GCC 9.x 版本在Godbolt上进行了尝试,它们都产生了相同的警告。 Clang versions however do not produce this error. Clang 版本但是不会产生此错误。

When variables smaller than int (like eg uint16_t ) are used with the bitwise complement operator ~ they are promoted to int .当小于int的变量(例如uint16_t )与按位补码运算~一起使用时,它们被提升为int

The type int is signed, and will not work well with shifting. int类型是有符号的,并且不适用于移位。 Especially considering that ~0 will be -1 with two's complement notation (which is the most common notation for representing negative numbers on binary systems).特别是考虑到~0将是带有二进制补码符号的-1 (这是在二进制系统上表示负数的最常见符号)。

A possible solution is to use larger unsigned types (like unsigned int ) and then use masking to get the relevant bits for the smaller type when done.一种可能的解决方案是使用较大的无符号类型(如unsigned int ),然后在完成后使用屏蔽来获取较小类型的相关位。

Warning is correct.警告是正确的。

~((uint16_t) 0) results in negative value, because result of (uint16_t) 0 is promoted to int before bitwise complement is performed. ~((uint16_t) 0)产生负值,因为(uint16_t) 0 uint16_t) 0 的结果在执行按位补码之前被提升为int

In general you should prefer unsigned integers (wide enough to avoid type promotion) when using bit shifting.通常,在使用位移时,您应该更喜欢无符号整数(足够宽以避免类型提升)。 My suggestion would be to use unsigned int zero instead:我的建议是使用unsigned int zero 代替:

return (~(~0U << shift));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM