merlin2011 merlin2011 - 2 months ago 17
C++ Question

How can I safely convert a wider integer type to a bitfield?

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))

Answer

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) & 0x00FFFFFFFFFFFFFF;