How can I safely convert a wider integer type to a

2019-02-23 20:52发布

Consider the following code.

#include <stdint.h>

struct MaskAndCount{
    uint64_t occupied : 56;
    uint8_t numOccupied : 8;
};

int main(){
    int count = 7;
    MaskAndCount foo;
    foo.occupied &= ~(1L << count);
}

If I compile this code with -Wconversion, then I will get the following error.

g++ -Wconversion Main.cc 
Main.cc: In function ‘int main()’:
Main.cc:11:18: warning: conversion to ‘long unsigned int:56’ from ‘long unsigned int’ may alter its value [-Wconversion]
     foo.occupied &= ~(1L << count);

This seems to be a legitimate concern, but my desired behavior is precisely to truncate all the higher bits of the value on the right.

My question is twofold.

  1. Will the conversion as written have the desired effect of truncating the higher bits of the value on the right?
  2. Is there is a way to either silence the warning locally or expressing the same behavior with a different syntax which does not trigger the warning?

Note that I have tried the following static cast, which does not compile at all.

static_cast<uint64_t:56>(~(1L << count))

标签: c++ g++
1条回答
Rolldiameter
2楼-- · 2019-02-23 21:14

As is the top bits (if set) will get ignored.

You can avoid the warning by removing the top bits yourself before the assignment:

int count = 7;
MaskAndCount foo = {};
                                // chop off the top 8 bits
foo.occupied &= ~(1 << count) & 0x00FFFFFFFFFFFFFFUL;

EDIT: Turns out this will not work for |= (not sure why). But that can be fixed by avoiding |= and using normal assignment:

foo.occupied = (foo.occupied & ~(1UL << count)) & 0x00FFFFFFFFFFFFFFUL;
foo.occupied = (foo.occupied | ~(1UL << count)) & 0x00FFFFFFFFFFFFFFUL;
查看更多
登录 后发表回答