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, 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’ fromlong unsigned int’ may alter its value [-Wconversion]
     foo.occupied &= ~(1L << count);

This seems like a legitimate problem, but my desired behavior is precisely to truncate all the most significant bits of the value on the right.

My question is twofold.

  • Will a written conversion have the desired effect of trimming the most significant bits of the value to the right?
  • Is there a way to either disable the warning locally, or express the same behavior with a different syntax that does not trigger the warning?

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

static_cast<uint64_t:56>(~(1L << count))
+4
source share
1

( ), .

, :

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

EDIT: , |= ( ). , |= :

foo.occupied = (foo.occupied & ~(1UL << count)) & 0x00FFFFFFFFFFFFFFUL;
foo.occupied = (foo.occupied | ~(1UL << count)) & 0x00FFFFFFFFFFFFFFUL;
+3

Source: https://habr.com/ru/post/1656852/


All Articles