如何将4个UINT8变量连接成一个UINT32变量?

M. *_*awy 3 c++ int bit-manipulation type-conversion visual-c++

我有以下UINT8变量:

UINT8 var1 = 0b00000001; //0000 0001
UINT8 var2 = 0b00000011; //0000 0011
UINT8 var3 = 0b00000111; //0000 0111
UINT8 var4 = 0b00001111; //0000 1111
Run Code Online (Sandbox Code Playgroud)

我想将这四个UINT8变量打包成一个UINT32变量,其值如下:

UINT32 var1 = 0b00000001000000110000011100001111; //00000001 00000011 00000111 00001111
Run Code Online (Sandbox Code Playgroud)

以下代码是否会正确安全地执行此操作?

UINT32 var1 = (var1<<24) + (var2<<16) + (var3<<8) + var4;
Run Code Online (Sandbox Code Playgroud)

Ken*_*rom 7

简短的回答,是的.

我不会担心你是如何写二进制数的.我将以十六进制输入它们,让你通过这个相关的SO问题寻找二进制表示:我可以在C或C++中使用二进制文字吗?

#include "stdafx.h"   // you are using devstudio
#include <Windows.h>  // you are using windows types
#include <iostream>   // I print out the result
#include <bitset>     // I use bitset to print the binary string

int main()
{
    UINT8 var1 = 0x01; //0000 0001
    UINT8 var2 = 0x03; //0000 0011
    UINT8 var3 = 0x07; //0000 0111
    UINT8 var4 = 0x0F; //0000 1111

    UINT32 bigvar = (var1 << 24) + (var2 << 16) + (var3 << 8) + var4;
    std::cout << std::bitset<32>(bigvar) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

你的数学是正确和安全的.这些字节是独立声明的,因此您不必担心字节顺序.这些类型都是无符号的,因此符号位没有UB问题.移位都适合正确的位数,因此没有溢出.我生成:

00000001000000110000011100001111
Run Code Online (Sandbox Code Playgroud)

或者,您可以读取32位整数作为4个字节,并重建32位数,但这不可移植,因为有时数字以相反的顺序存储.例如,在TIFF中,您读入一个标题值,该值告诉您是先将var1放在第一位还是向上计数,或先将var4放在第四位并倒计时.在将一堆字节组合成更大的整数类型的几乎所有实际应用中,字节顺序是您必须注意的.查看big-endian和little-endian以获取更多信息.

  • *"你的数学是正确和安全的."*不,不是.`var1 << 24`可能是UB. (4认同)
  • `24`已签署. (3认同)
  • 它通过转移到符号位(在你的平台上给定`int`是32位)为所有`var1> 127`调用UB. (2认同)
  • 事实证明我错了,结果只是实现定义,并且在大多数平台上(即那些实现2s补充整数数学的那些,如gcc,clang,icc,MSVC ..)我们将始终得到正确的结果.然而,比你意识到的还要多.对于初学者来说,`var1 << 24`相当于`int(var1)<< 24`,即你的LHS*是*签名的,但5.8/2修复了我们的溢出.如果您想查看详细信息,请随时提出新问题.Monkey链接问题的答案也解释了.无论如何,downvote删除. (2认同)