c++ - 使用固定大小类型时强制位字段符号 (pre-C++14)

标签 c++ language-lawyer bit-fields

基本问题请跳到粗体部分,其余只是背景。

由于我不想深入的原因,我正在编写一个代码生成器,它在(非常)pre-C++14 环境中生成 C++ 结构。生成器必须创建位域;它还需要以尽可能便携的方式尽可能严格地控制生成字段的行为。我需要控制底层分配单元的大小,以及如何处理带符号的值。我不会解释为什么我会做这样一个傻瓜差事,这显然与实现定义的行为相冲突,但涉及到薪水,并且所有正确的方法来做需要做的事情都被人们拒绝了谁安排薪水。

所以我一直在生成类似这样的东西:

int32_t x : 11;

因为我需要让编译器相信这个字段(以及具有相同底层类型的其他相邻字段)存在于一个 32 位字中。为基础类型生成 int 不是一个选项,因为 int 没有固定的大小,并且当有人发布 int 是 64 位宽的编译器的那一天,事情会变得非常错误,或者我们结束回到 16 点。

在 C++14 之前的版本中,int x: 11 可能是也可能不是无符号字段,您可以在前面加上显式的 signedunsigned 来获得你所需要的。我担心 int32_t 和它的 friend 们会有同样的歧义(为什么不呢?)但是编译器正在对 signed int32_t 进行限制。

C++ 标准是否有关于 intxx_t 类型是否将其符号强加给位字段的任何文字?如果没有,是否可以保证类似的东西

typedef signed int I32;
...
I32 x : 11;
...
assert(sizeof(I32)==4); //when this breaks, you won't have fun

将带符号的指示符带入位域?

请注意,任何以“只生成一个函数来……”开头的建议都是不予考虑的。这些生成的 header 将被插入到执行类似 s->x = 17; 之类的代码中。我已经很好地向我解释说,我绝不能建议将它全部更改为 s->set_x(17) 甚至再一次。即使我可以简单地生成一个 set_x 函数来准确和安全地做我需要的事情,而根本没有任何实现定义的行为。此外,我非常了解位字段的变幻莫测,从左到右、从右到左、从里到外以及编译器处理它们的任何其他方式,以及为什么这是傻瓜差事的其他几个原因。而且我不能只是“尝试一些东西”,因为这需要在我没有的编译器上工作,这就是为什么我在标准中争先恐后地保证。

注意:我无法实现任何不允许现有代码简单地将指向字节缓冲区的指针转换为指向生成的结构的指针,然后使用它们的指针获取要读写的字段的解决方案.现有代码都是关于 s->x 的,并且必须在不做任何更改的情况下工作。这排除了在生成的代码中涉及构造函数的任何解决方案。

最佳答案

Does the C++ standard have any words on whether the intxx_t types impose their signedness on bit fields?

没有。


<cstdint> 的固定宽度整数的标准概要, [cstdint.syn] (链接到现代标准;概要的相关部分在 the C++11 standard 中看起来相同)只是简单地指定,描述性地(不是通过 signed/unsigned 关键字),他们应该是“有符号整数类型”“无符号整数类型”

例如for gcc , <cstdint>暴露the fixed width integers of <stdint.h> ,这又是预定义预处理器宏的类型定义(例如 __INT32_TYPE__ int32_t ),后者是特定于平台的。

该标准未强制要求使用 signedunsigned本概要中的关键字,以及因此固定宽度整数类型的位字段,在 C++11 中,将遭受与声明普通整数位字段时相同的实现定义的关于其符号性的行为。回想一下 [class.bit]/3 在 C++14 之前的相关部分是(在由于 CWG 739 采取行动之前):

It is implementation-defined whether a plain (neither explicitly signed nor unsigned) char, short, int, long, or long long bit-field is signed or unsigned. ...

确实是下面的线程

显示了一个示例,例如__INT32_TYPE__在回答者的特定平台上定义时没有明确存在 signed关键词:

$ gcc -dM -E  - < /dev/null | grep __INT
...
#define __INT32_TYPE__ int

关于c++ - 使用固定大小类型时强制位字段符号 (pre-C++14),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55883152/

相关文章:

c++ - 折叠表达式的结合性

c++ - 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?

c++ - C 和 C++ 中的位字段 : where are they used?

c++ - 成员结构位域元素的初始化列表初始化导致 IAR ARM 中的错误

c++ - 使用 QAtomicInt/QAtomicPointer 进行原子读取

c++ - 以编程方式在 IE 中设置页面缩放和文本大小

c - C : Nested blocks 中的作用域规则

c++ - C/C++ 位域与按位运算符区分位,哪个更快、更好、更便携?

c++ - 模板化转换运算符类型推导在 clang 和 gcc 中不同

c++ - 强制 Boost 使用 C++11 线程