简体   繁体   中英

compiler warning: left shift of negative value

I think GCC is wrongfully producing a [-Wshift-negative-value] warning.

I have a function that should produce a suffix mask of a certain length provided by its single input argument:

#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

-Werror -Wextra

This warning also occurs if I change the output from uint16_t to uint8_t . Bigger output types, ie uint32_t don't produce this warning.

I am using an older version of 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. Clang versions however do not produce this error.

When variables smaller than int (like eg uint16_t ) are used with the bitwise complement operator ~ they are promoted to int .

The type int is signed, and will not work well with shifting. 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).

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.

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.

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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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