Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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++ 在C+中,将位字段结构转换为int+;_C++_C++11_Visual C++_Bit Fields_Reinterpret Cast - Fatal编程技术网

C++ 在C+中,将位字段结构转换为int+;

C++ 在C+中,将位字段结构转换为int+;,c++,c++11,visual-c++,bit-fields,reinterpret-cast,C++,C++11,Visual C++,Bit Fields,Reinterpret Cast,我有一个具有相同类型成员的结构。我正在尝试将其转换为uint8\t类型。我可以这样做,但看不到输出。请告诉我哪里出了问题。我也知道还有其他的方法吗?我尝试这样做是因为我想习惯static\u cast和reinterpret\u cast 代码如下: int main() { struct xs{ bool x :1 ; bool y :1; bool z :1; uint8_t num :5; } zs;

我有一个具有相同类型成员的结构。我正在尝试将其转换为
uint8\t
类型。我可以这样做,但看不到输出。请告诉我哪里出了问题。我也知道还有其他的方法吗?我尝试这样做是因为我想习惯
static\u cast
reinterpret\u cast

代码如下:

int main()
{
    struct xs{
        bool x :1 ;
        bool y :1;
        bool z :1;
        uint8_t num :5;
    } zs;

    uint8_t* P = static_cast<uint8_t*>(static_cast<void*>(&zs));

    cout << *P << endl;

    return 0;
}
intmain()
{
结构xs{
boolx:1;
booly:1;
boolz:1;
uint8_t num:5;
}zs;
uint8_t*P=静态_cast(静态_cast(&zs));
库特
  • 通过指向对象类型以外的类型的指针访问对象是一种未定义的行为。它适用于大多数编译器,但从技术上讲,您的程序可以做任何它想做的事情

  • 假设我们没有遇到1中提到的问题,我猜uint8_t是char的别名,所以cout会将char放在控制台上。 您没有初始化正在检查的内存,因此它可以是0。值为0的字符不会在控制台中打印任何“可观察”的内容,请查看ascii表。例如,尝试用50填充结构


  • 这里有两件事需要解决。首先,正如一些人指出的那样,您不能以这种方式访问对象。如果您想正确构造uint8,您需要读取结构中的变量并进行一些位移位,例如:

    uint8_t value = 0;
    value |= (zs.x ? 1 << 7 : 0);
    value |= (zs.y ? 1 << 6 : 0);
    value |= (zs.z ? 1 << 5 : 0);
    value |= zs.num;
    
    uint8\u t值=0;
    
    值|=(zs.x?1这里有很多问题:

  • 您似乎认为
    x
    y
    z
    将全部打包到单个
    uint_8
    中。事实并非如此。“然后,编译器可以将相同类型的相邻声明位字段打包成更少的字。”
  • “sizeof(bool)
  • 的值由实现定义,可能与1不同”,因此您的
    xs
    将由实现定义,但肯定不等同于
    sizeof(uint_8)
  • 因为
    xs
    uint_8
    不“相似”,根据
    重新解释的行为,cast
    未定义
  • 最后,您看不到任何内容的原因是,无论实现定义的值在
    *P
    处,当被
    cout
    视为
    char
  • 代码的一个可能解决方法是使用以下定义:

    constexpr uint8_t X = 0B1000'0000;
    constexpr uint8_t Y = 0B0100'0000;
    constexpr uint8_t Z = 0B0010'0000;
    constexpr uint8_t NUM = 0B0001'1111;
    
    uint8_t zs;
    
    然后,如果为
    zs
    分配了一些值,则可以执行以下功能以输出前一个位字段:

    cout << ((zs & X) != 0) << endl;
    cout << ((zs & Y) != 0) << endl;
    cout << ((zs & Z) != 0) << endl;
    cout << (zs & NUM) << endl;
    

    一个
    uint8\u t
    实际上是一个
    无符号字符,因此将被打印为一些ascii字符,很可能不是一个可见字符。将其转换为其他整数类型。但请记住你在做什么(将一个类型视为它不是的类型)太可怕了,无法保证会发生什么。@BoBTFish尝试使用char-type仍然没有输出@BoBTFish说这是未定义的行为。
    struct xs
    的大小和布局是由实现定义的,在大小上可能不是
    uint8\u t
    。即使是这样,您的强制转换也被定义为不起作用。See在中指出:只是一个警告:也许“习惯”重新解释强制转换不是最好的主意。重新解释强制转换用于特殊情况,不应该经常使用,实际上它们是红色信号,表明正在发生奇怪的事情。“你没有初始化正在检查的内存,所以它可以是0”不,它将是未初始化的垃圾。我不认为它是UB。对于类型为
    char*
    unsigned char*
    std::byte*
    @JonathanWakely的指针有一个例外。从技术上讲,根据标准its垃圾,它可以是0:P。我最初想到的是编译器的“扩展”int只能在调试模式下初始化为零。我想我在某个地方读到过visual studio这样做的内容?但我可能在这里大错特错。所以我让它打开到“它可以是0”。@Jens你是对的。但是uint8\u不总是(!)别名字符、无符号字符或字节?@phön你说得对。
    std::uint8_t
    可以是正好是8位的任何类型,因此即使
    char_位==8
    也可以是其他类型。
    char
    也可以大于8位(这会使
    sizeof
    有趣,因为它是
    sizeof(char)
    的倍数),在这种情况下,
    std::uint8\u t
    没有什么不同。我在现实生活中从未见过这种情况。谢谢你,你在“1”中描述的正是我想要的。我现在尝试实现int*P=static\u cast(static\u cast(&zs));它是有效的。但是,如果我定义x为真,那么输出为1,但是如果我定义y为真,那么输出为2。它的工作顺序是这样的。谢谢。我想我知道它在8421规则中工作,因为根据位位置它给了我一个整数。但是当试图在那里使用char而不是int时,y不起作用。你有什么理由告诉我们吗ed
    #为常数定义
    ?这似乎是初学者的问题,所以我不会展示一些你不应该使用的东西。@Mandeep我恐怕至少我不明白你在说什么。8421是什么?你在哪里使用字符而不是int?代码中没有
    int
    。@Jen没有特别的原因。
    const uint8\t x=0B1000'0000
    的工作原理与
    #define
    的工作原理相同
    cout << ((zs & X) != 0) << endl;
    cout << ((zs & Y) != 0) << endl;
    cout << ((zs & Z) != 0) << endl;
    cout << (zs & NUM) << endl;