如何安全地将更宽的整数类型转换为位域

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

本文关键字:整数 类型转换 位域 何安全 安全      更新时间:2023-10-16

考虑以下代码:

#include <stdint.h>
struct MaskAndCount{
    uint64_t occupied : 56;
    uint8_t numOccupied : 8;
};
int main(){
    int count = 7;
    MaskAndCount foo;
    foo.occupied &= ~(1L << count);
}

如果我用-Wconversion编译这段代码,那么我将得到以下错误:

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

这似乎是一个合理的问题,但我想要的行为恰恰是截断右边所有高位数的值。

我的问题是双重的。

  1. 转换是否具有截断右侧值的较高位的预期效果?
  2. 是否有一种方法可以在本地沉默警告或用不同的语法表达相同的行为,而不触发警告?

请注意,我已经尝试了以下静态强制转换,它根本无法编译。

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

如果设置了顶部位,则会被忽略。

您可以通过在赋值前自己删除顶部位来避免此警告:

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;