首页 > 其他分享 >将一个结构体里面的数据转为 小端对齐的二进制流

将一个结构体里面的数据转为 小端对齐的二进制流

时间:2024-04-08 23:12:31浏览次数:29  
标签:小端 test1 00 二进制 std 对齐 sizeof block appendLittleEndian

现在有一个C++的结构体,需要把它转为二进制流,而且是小端对齐的。

我们还需要将一个小端对齐的二进制流,转为对应的结构体。

appendLittleEndian
parseLittleEndian

这2个方法是chatgpt提供给我的,功能能准确实现。代码也比较简洁。

 

#include <iostream>  
#include <vector>
#include <cstring>
#include <iomanip>

typedef struct tagInfoA {
    uint8_t    Ver;
    uint16_t   Code;
    uint8_t    Reserve;
    uint16_t   Length;
    uint16_t   AttrCount;

    uint32_t   a;
    uint32_t   b;
    int        c;
    char       szBuf1[10];
    char       szBuf2[10];
    int        d;
} INFOA_DEF;

bool isLittleEndian() {
    uint32_t num = 0x01020304;
    uint8_t* ptr = reinterpret_cast<uint8_t*>(&num);
    return (*ptr == 0x04); // If the least significant byte (LSB) is 0x04, then it's little-endian
}

void appendLittleEndian(std::vector<uint8_t>& block, const void* data, size_t size) {
    const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
    for (size_t i = 0; i < size; ++i) {
        block.push_back(*ptr);
        ++ptr;
    }
}

template<typename T>
void parseLittleEndian(const std::vector<uint8_t>& block, size_t& offset, T& value) {
    std::memcpy(&value, &block[offset], sizeof(T));
    offset += sizeof(T);
}

int main() {  
    if (isLittleEndian()) {
        std::cout << "Current machine is little-endian.\n";
    } else {
        std::cout << "Current machine is big-endian.\n";
    }

    std::vector<uint8_t> block;
    INFOA_DEF test1;
    test1.Ver = 0x01;
    test1.Code = 0x0203;
    test1.Reserve = 0x04;
    test1.Length = 0x0506;
    test1.AttrCount = 0x0708;
    test1.a = 0x1234;
    test1.b = 0x5678;
    test1.c = 0xabcd;
    std::memcpy(test1.szBuf1, "12345", 6); // Copy only 6 characters to leave space for null terminator
    std::memcpy(test1.szBuf2, "abcdefg", 8); // Copy only 8 characters to leave space for null terminator
    test1.d = 400;

    // Convert struct to little-endian byte stream
    appendLittleEndian(block, &test1.Ver, sizeof(test1.Ver));
    appendLittleEndian(block, &test1.Code, sizeof(test1.Code));
    appendLittleEndian(block, &test1.Reserve, sizeof(test1.Reserve));
    appendLittleEndian(block, &test1.Length, sizeof(test1.Length));
    appendLittleEndian(block, &test1.AttrCount, sizeof(test1.AttrCount));
    appendLittleEndian(block, &test1.a, sizeof(test1.a));
    appendLittleEndian(block, &test1.b, sizeof(test1.b));
    appendLittleEndian(block, &test1.c, sizeof(test1.c));
    appendLittleEndian(block, test1.szBuf1, sizeof(test1.szBuf1));
    appendLittleEndian(block, test1.szBuf2, sizeof(test1.szBuf2));
    appendLittleEndian(block, &test1.d, sizeof(test1.d));

    // Output binary stream
    std::cout << "Binary Stream in little-endian format:\n";
    for (uint8_t byte : block) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(byte) << " ";
    }
    std::cout << std::endl;

    // Parse binary stream back to struct
    size_t offset = 0;
    INFOA_DEF parsedData;
    parseLittleEndian(block, offset, parsedData.Ver);
    parseLittleEndian(block, offset, parsedData.Code);
    parseLittleEndian(block, offset, parsedData.Reserve);
    parseLittleEndian(block, offset, parsedData.Length);
    parseLittleEndian(block, offset, parsedData.AttrCount);
    parseLittleEndian(block, offset, parsedData.a);
    parseLittleEndian(block, offset, parsedData.b);
    parseLittleEndian(block, offset, parsedData.c);
    std::memcpy(parsedData.szBuf1, &block[offset], sizeof(parsedData.szBuf1));
    offset += sizeof(parsedData.szBuf1);
    std::memcpy(parsedData.szBuf2, &block[offset], sizeof(parsedData.szBuf2));
    offset += sizeof(parsedData.szBuf2);
    parseLittleEndian(block, offset, parsedData.d);

    // Output parsed struct
    std::cout << "\nParsed Data:\n";
    std::cout << "Ver: " << std::hex << static_cast<int>(parsedData.Ver) << std::endl;
    std::cout << "Code: " << std::hex << static_cast<int>(parsedData.Code) << std::endl;
    std::cout << "Reserve: " << std::hex << static_cast<int>(parsedData.Reserve) << std::endl;
    std::cout << "Length: " << std::hex << static_cast<int>(parsedData.Length) << std::endl;
    std::cout << "AttrCount: " << std::hex << static_cast<int>(parsedData.AttrCount) << std::endl;
    std::cout << "a: " << std::hex << parsedData.a << std::endl;
    std::cout << "b: " << std::hex << parsedData.b << std::endl;
    std::cout << "c: " << std::hex << parsedData.c << std::endl;
    std::cout << "szBuf1: " << parsedData.szBuf1 << std::endl;
    std::cout << "szBuf2: " << parsedData.szBuf2 << std::endl;
    std::cout << "d: " << std::dec << parsedData.d << std::endl;

    return 0;  
}

 

打印的结果:

Current machine is little-endian.
Binary Stream in little-endian format:
01 03 02 04 06 05 08 07 34 12 00 00 78 56 00 00 cd ab 00 00 31 32 33 34 35 00 00 00 b0 30 61 62 63 64 65 66 67 00 40 00 90 01 00 00 

Parsed Data:
Ver: 1
Code: 203
Reserve: 4
Length: 506
AttrCount: 708
a: 1234
b: 5678
c: abcd
szBuf1: 12345
szBuf2: abcdefg
d: 400

 

标签:小端,test1,00,二进制,std,对齐,sizeof,block,appendLittleEndian
From: https://www.cnblogs.com/music-liang/p/18122881

相关文章

  • 进制之间的转换之“十六进制 转 十进制 转 二进制 方案”
    1.十六进制转十进制十六进制数为:0X1A6F根据16进制数要转十进制得到公式:F*160+6*161+A*162 +1*163 十六机制数:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F也就是常数:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15转为常数:15 *160 +6*161 +10*162 +1*163 计......
  • js context.fillText 征对不同长度右边对齐的解决办法
    在HTML5Canvas中,要实现文本右对齐并且与不同长度文本互不重叠,可以通过测量文本宽度,并基于文本宽度设置x坐标来实现。以下是一个简单的JavaScript函数,用于在Canvas中右对齐并且不重叠地绘制文本:functiondrawRightAlignedText(context,text,x,y){//测量文本宽度......
  • 二进制和位运算
    1.无符号:int32位可以表示0~2^32-1位数。2.有符号:负数占1/2,正数和0占1/2首位为0表示非负。首位为1表示负数,后面是数值位。-1表示:先看正数:0001为1,减1——>0000表示0,每一位取反——>1111。-2表示:先看正数:0010,减1(向高位借位)——>0001表示1,取反——>1110。-8:1110,减1......
  • 如何把一个十进制数转化为一个二进制数
    起因Miqa在改愤怒的小鸟,WA了两个点,尝试画图未遂,于是开调,但是想直观的看到二进制数,所以有了这个工具。#include<bits/stdc++.h>usingnamespacestd;inlinevoidtwice(longlongx){ stack<int>num; while(x!=0) { if(x&1)num.push(1); elsenum.push(0); x>>=1; ......
  • ctfshow--web9 md5二进制格加密的绕过
    dirsearch扫到robots文件查看一下发现有个index.phps文件访问这个index.phps,可以下载下来我们来审计一下这里的代码<?php$flag=""; $password=$_POST['password']; if(strlen($password)>10){ die("passworderror"); } $sql="select*from......
  • C语言02-常量、二进制、数据类型
    第4章常量1.常量特点程序运行时,其值不能改变的量,即为常量。习惯上常量名使用大写,方便与变量区分。2.常量分类​ **字面量常量**:直接使用的常量,不需要定义或声明,包括整数常量、浮点数常量、字符常量。注:有1,2,3等 ——顾名思义,就是数字整数 1.2,1.3,1.4等 ——也就......
  • 芒果YOLOv5改进90:标签分配策略篇之TOOD:最新基于Task-aligned Assignment任务对齐学习T
    芒果专栏基于TOOD的改进,改进Task-alignedAssignment任务对齐学习源码教程|详情如下......
  • 芒果YOLOv7改进90:标签分配策略篇之TAL:最新基于Task-aligned Assignment任务对齐学习TA
    芒果专栏基于TOOD的改进,改进Task-alignedAssignment任务对齐学习源码教程|详情如下......
  • 整型之韵,数之舞:大小端与浮点数的内存之旅
    ✨✨欢迎......
  • 大端序,小端序,Big-endian, Little-endian
    在计算机中,字节序(byteorder)指的是多字节数据在存储时字节的排列顺序。主要有两种字节序:大端序(big-endian)和小端序(little-endian)。大端序(Big-endian):在大端序中,最高有效字节(MostSignificantByte,MSB)存储在最低的内存地址,而最低有效字节(LeastSignificantByte,LSB)存储在最高的内......