The issue

low level bare-metal embedded上下文中,我想在内存中创建一个空白,在C++ struct 内,没有任何名称,以禁止用户访问这样的内存位置.

现在,我已经通过放置一个丑陋的uint32_t :96;bit字段来实现它,它可以方便地取代三个单词,但它会引起GCC(Bitfield太大,不适合uint32_t)的警告,这是相当合法的.

虽然它工作得很好,但当你想要发布一个包含数百个警告的库时,它不是很干净...

How do I do that properly?

Why is there an issue in the first place?

我正在做的项目包括定义整个微控制器系列(STMicroelectronics STM32)不同外设的内存 struct .要做到这一点,结果是一个类,它包含多个 struct 的并集,这些 struct 定义了所有寄存器,具体取决于目标微控制器.

一个简单的外设示例如下:通用输入/输出(GPIO)

union
{

    struct
    {
        GPIO_MAP0_MODER;
        GPIO_MAP0_OTYPER;
        GPIO_MAP0_OSPEEDR;
        GPIO_MAP0_PUPDR;
        GPIO_MAP0_IDR;
        GPIO_MAP0_ODR;
        GPIO_MAP0_BSRR;
        GPIO_MAP0_LCKR;
        GPIO_MAP0_AFR;
        GPIO_MAP0_BRR;
        GPIO_MAP0_ASCR;
    };
    struct
    {
        GPIO_MAP1_CRL;
        GPIO_MAP1_CRH;
        GPIO_MAP1_IDR;
        GPIO_MAP1_ODR;
        GPIO_MAP1_BSRR;
        GPIO_MAP1_BRR;
        GPIO_MAP1_LCKR;
        uint32_t :32;
        GPIO_MAP1_AFRL;
        GPIO_MAP1_AFRH;
        uint32_t :64;
    };
    struct
    {
        uint32_t :192;
        GPIO_MAP2_BSRRL;
        GPIO_MAP2_BSRRH;
        uint32_t :160;
    };
};

其中所有GPIO_MAPx_YYY是一个宏,定义为uint32_t :32或寄存器类型(专用 struct ).

在这里,你可以看到uint32_t :192;很好地工作,但它会触发一个警告.

What I've considered so far:

我可能会用uint32_t :32;(这里是6)来代替它,但我有一些极端的例子,其中有uint32_t :1344;(42)(等等).所以我不想在8k行的基础上再增加大约uint32_t :32;行,即使 struct 生成是脚本化的.

确切的警告信息如下:

我宁愿通过简单地删除警告来解决这个问题,但是使用

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop

可能是一种解决方案...如果我找到TheRightFlag的话.然而,正如在this thread,gcc/cp/class.c中使用这段可悲的代码部分所指出的那样:

warning_at (DECL_SOURCE_LOCATION (field), 0,
        "width of %qD exceeds its type", field);

这告诉我们没有-Wxxx个标志来删除这个警告...

推荐答案

使用多个相邻的匿名位域.所以不是:

    uint32_t :160;

例如,您将拥有:

    uint32_t :32;
    uint32_t :32;
    uint32_t :32;
    uint32_t :32;
    uint32_t :32;

你想匿名的每一个注册都有一个.

如果需要填充较大的空间,则使用宏重复单个32位空间可能会更清晰、更不容易出错.例如,假设:

#define REPEAT_2(a) a a
#define REPEAT_4(a) REPEAT_2(a) REPEAT_2(a)
#define REPEAT_8(a) REPEAT_4(a) REPEAT_4(a)
#define REPEAT_16(a) REPEAT_8(a) REPEAT_8(a)
#define REPEAT_32(a) REPEAT_16(a) REPEAT_16(a)

则可以添加1344(42*32位)空间,如下所示:

struct
{
    ...
    REPEAT_32(uint32_t :32;) 
    REPEAT_8(uint32_t :32;) 
    REPEAT_2(uint32_t :32;)
    ...
};

C++相关问答推荐

C strlen on char array

如何解决C中的严格别名?

如何在C++中处理按键

如何使解释器存储变量

RawMotion的XInput2错误(具有较高值的XISelectEvents上的BadValue)

在编写代码时,Clion比vscode有更多的问题指示器

如何将C中的两个字符串与从文件接收的字符串中的字符数进行比较

Printf()在C中打印终止字符之后的字符,我该如何解决这个问题?

判断系统命令返回值的正确方法

使用C++中的字符串初始化 struct 时,从‘char*’初始化‘char’使指针变为整数,而不进行强制转换

按字典顺序打印具有给定字符的所有可能字符串

如何不断地用C读取文件?

这些表达式是否涉及 C 中定义的复合文字?

使用替代日历打印日期

是什么阻止编译器优化手写的 memcmp()?

如何转义包含指令中的字符?

段错误try 访问静态字符串,但仅有时取决于构建环境

使用 SDL2 的 C 程序中的内存泄漏

米斯拉映射到 klocwork 违规行为

在 C 语言中,类型object_t在哪里定义?