Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在使用固定大小类型时强制对位字段(pre-C+;和#x2B;14)进行签名_C++_Language Lawyer_Bit Fields - Fatal编程技术网

C++ 在使用固定大小类型时强制对位字段(pre-C+;和#x2B;14)进行签名

C++ 在使用固定大小类型时强制对位字段(pre-C+;和#x2B;14)进行签名,c++,language-lawyer,bit-fields,C++,Language Lawyer,Bit Fields,对于基本问题,请跳到粗体部分,其余部分只是背景 因为我不想进入的原因,我正在编写一个代码生成器,它在非常(非常)的C++ 14环境中生成C++结构。生成器必须创建位字段;它还需要以尽可能便携的方式对生成字段的行为进行尽可能严格的控制。我需要控制底层分配单元的大小,以及如何处理有符号值。我不想解释为什么我要做这样一件傻事,这显然与实现定义的行为相冲突,但这涉及到薪水,所有需要做的正确方法都被安排薪水的人拒绝了 因此,我一直在生成以下内容: int32_t x : 11; 因为我需要让编译器相信这

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

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

因此,我一直在生成以下内容:

int32_t x : 11;
因为我需要让编译器相信这个字段(以及具有相同底层类型的其他相邻字段)存在于32位字中。为基础类型生成
int
不是一个选项,因为int没有固定的大小,如果有人发布int为64位宽的编译器,或者我们回到int为16位的编译器,事情就会变得非常糟糕

在C++14之前的版本中,
intx:11
可能是也可能不是一个无符号字段,您可以预先添加一个显式的
signed
unsigned
,以获得所需的内容。我担心int32_t和friends也会有同样的歧义(为什么不呢?),但编译器正在堵住
签名int32_t

<>强> C++标准是否有关于ixxx类型在比特域上施加其SIGNND的词?< /强>如果没有,有没有保证像

之类的东西?
typedef signed int I32;
...
I32 x : 11;
...
assert(sizeof(I32)==4); //when this breaks, you won't have fun
是否将带符号的指示符带入位字段

请注意,任何以“只生成一个函数…”开头的建议都是菲亚特提出的。这些生成的头文件将被插入到代码中,这些代码执行类似于s->x=17的操作;我已经得到了很好的解释,我不能再建议把它全部改成
s->set_x(17)
。即使我可以简单地生成一个set_x函数来准确、安全地完成我需要的工作,而不需要任何实现定义的行为。此外,我非常了解位字段的变化,从左到右、从右到左、从内到外,以及编译器所能做的任何其他事情,还有其他几个原因,为什么这是一件愚蠢的差事。我不能只是“尝试东西”,因为这需要在我没有的编译器上工作,这就是为什么我要在标准中争取保证

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

它还需要以尽可能便携的方式对生成字段的行为进行尽可能严格的控制。我需要控制底层分配单元的大小,以及如何处理有符号值

这两个目标是不相容的。位字段本身就存在可移植性问题

如果该标准定义了您想要的行为,那么“位字段的变化无常”就不存在了,人们也不会为推荐使用位掩码和移位来实现可移植性而烦恼

您可能要做的是提供一个类,该类使用位字段公开与
结构相同的接口,但实际上不在内部使用位字段。然后,您可以通过掩码和移位使其构造函数和析构函数可移植地读取或写入这些字段。例如,类似于:

class BitfieldProxy
{
public:
    BitfieldProxy(uint32_t& u)
    : x((u >> 4) & 0x7FF),
      y(u & 0xF),
      mDest(u)
    {
    }

    ~BitfieldProxy()
    {
        assert((x & 0x7FF) == x);
        assert((y & 0xF) == y);
        dest = (x << 4) | y;
    }

    BitfieldProxy(const BitfieldProxy&) = delete;
    BitfieldProxy& operator=(const BitfieldProxy&) = delete;

    // Only the last 11 bits are valid.
    unsigned int x;

    // Only the last 4 bits are valid.
    unsigned int y;

private:
    uint32_t& mDest;
};
类BitfieldProxy
{
公众:
比特域代理(uint32\u t&u)
:x((u>>4)和0x7FF),
y(u&0xF),
mDest(美国)
{
}
~BitfieldProxy()
{
断言((x&0x7FF)==x);
断言((y&0xF)==y);
dest=(x

C++标准是否有关于ixxxt类型在位字段上施加其SIGNNED的词?< /P> 没有


本标准关于
的固定宽度整数的概要(链接到现代标准;概要的相关部分在中看起来相同)简单地描述(而不是通过
有符号
/
无符号
关键字)规定它们应为“有符号整数类型”或“无符号整数类型”

例如,
expose,它又是预定义的预处理器宏的typedef(例如,
int32\t
),后者是特定于平台的

本标准没有强制要求在本概要中使用
有符号
无符号
关键字,因此,在C++11中,固定宽度整数类型的位字段在其符号性方面将遭受与声明普通整数位字段时相同的实现定义行为C++14之前的[class.bit]/3的一部分是(由于以下原因而在操作之前):

由实现定义一个普通(既不是显式签名也不是无符号的)
char
short
int
long
、或
long
位字段是有符号的还是无符号的

事实上,以下线索

显示了一个示例,其中应答者特定平台上的
\uuuuuu INT32\u TYPE\uuuuuuuu
定义没有明确的
签名关键字:

$gcc-dM-E-
我认为你是说“C++标准有没有关于iTxxt类型在比特域上施加其SIGNID的词”吗?不,好吧,但是你能引用一个或一个章节吗?我应该提到没有机会运行构造函数,也没有修改。
$ gcc -dM -E  - < /dev/null | grep __INT
...
#define __INT32_TYPE__ int