c++ - 如何摆脱结构的数据成员之间的填充字节

标签 c++ struct stream binary-data

我有一个带有“消息”的二进制文件,我正在尝试使用结构将字节放入正确的变量中。在我的示例中,我使用了两种类型的消息:Tmessage 和 Amessage。

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
#include <iomanip>

using namespace std;

struct Tmessage
{
    unsigned short int Length;
    char MessageType;
    unsigned int Second;
};

struct Amessage
{
    unsigned short int Length;
    char MessageType;
    unsigned int Timestamp;
    unsigned long long int OrderReferenceNumber;
    char BuySellIndicator;
    unsigned int Shares;
    char Stock[6];
    unsigned int Price;
};

int main(int argc, char* argv[])
{
    const char* filename = argv[1];
    fstream file(filename, ios::in | ios::binary);
    unsigned long long int pi = 0;

    if(file.is_open()){ cout << filename << " OPENED" << endl; }
    else { cout << "FILE NOT OPENED" << endl; }

    unsigned char* memblock;
    memblock = new unsigned char[128];
    file.read((char *)memblock, 128);

    cout <<  "BINARY DATA" << endl;
    while (pi < 128)
    {
        cout << setw(2) << hex << static_cast<unsigned int>(memblock[pi]) << " ";
        pi++;
        if((pi%16)==0) cout << endl;
    }

    unsigned int poi = 0;

    Tmessage *Trecord;
    Trecord = (Tmessage *)memblock;
    cout << "Length: " << hex << (*Trecord).Length << endl;
    cout << "Message type: " << hex << (*Trecord).MessageType << endl;
    cout << "Second: " << hex << (*Trecord).Second << endl;

    poi = poi + 7; cout << endl;

    Amessage *Arecord;
    Arecord = (Amessage *)(memblock+poi);
    cout << "Length: " << hex << (*Arecord).Length << endl;
    cout << "Message type: " << hex << (*Arecord).MessageType << endl;
    cout << "Timestamp: " << hex << (*Arecord).Timestamp << endl;
    cout << "OrderReferenceNumber: " << hex << (*Arecord).OrderReferenceNumber << endl;
    cout << "BuySellIndicator: " << hex << (*Arecord).BuySellIndicator << endl;
    cout << "Shares: " << hex << (*Arecord).Shares << endl;
    cout << "Stock: " << hex << (*Arecord).Stock << endl;
    cout << "Price: " << hex << (*Arecord).Price << endl;

    delete memblock;
    file.close();
    cout << endl << "THE END" << endl;
    return 0;
}

程序运行时的输出:

stream OPENED
BINARY DATA
 0  5 54  0  0 62 72  0 1c 41  0  f 42 40  0  0 
 0  0  0  4 2f 76 53  0  0  3 e8 53 50 59 20 20 
20  0 11  5 d0  0 1c 41  0  f 42 40  0  0  0  0 
 0  4 2f 78 42  0  0  3 e8 53 50 59 20 20 20  0 
10 f7 5c  0 1c 41  0  f 42 40  0  0  0  0  0  4 
2f 90 53  0  0  1 2c 53 50 59 20 20 20  0 11  2 
b0  0  5 54  0  0 62 76  0  d 44 14 25 78 80  0 
 0  0  0  0  4 2f 90  0  d 44 14 25 78 80  0  0 
Length: 500
Message type: T
Second: 726200

Length: 1c00
Message type: A
Timestamp: 40420f
OrderReferenceNumber: 53762f0400000000
BuySellIndicator: 
Shares: 20595053
Stock:   
Price: 420f0041

THE END

程序将字节正确地放置在 Tmessage 结构中。 (0 5 54 0 0 62 72)
但是,在解析 Amessage 时发生了一些事情。
(0 1c 41 0 f 42 40 0 0 0 0 0 4 2f 76 53 0 0 3 e8 53 50 59 20 20 20 0 11 5 d0)

Lenght、MessageType 和 Timestamp 正确,但 OrderReferenceNumber 包含属于 BuySellIndicator 的“53”字节,然后其他变量不正确。

正确的A消息输出应该是:
长度:1c 0
消息类型:41
时间戳:40 42 f 0
订单编号:76 2f 4 0 0 0 0 0
买入卖出指标:53
份额:e8 3 0 0
库存:53 50 59 20 20 20
价格:d0 5 11 0

两个问题: a) 为什么 OrderReferenceNumber 包含“53”字节? b) 我认为“char Stock[6]”不起作用,因为在 Share 的字节和 Price 的字节之间有超过 6 个字节。如何将 6 个字节放入 char vector 或字符串中?

注意:我知道我必须交换字节,因为二进制数据采用大端格式。这就是为什么不应该交换“股票”的原因。 非常感谢您的帮助!亲切的问候,

最佳答案

结构的数据成员之间可能有未命名的填充字节。

为了以可移植的方式从文件中读取二进制数据,您应该单独读取结构的每个成员。

您还应该使用 <cstdint> 中指定的确切宽度类型(如果您的标准库还没有,Boost 有这个头文件的实现);这将使您能够确保数据成员的大小与消息中字段的大小相匹配。

关于c++ - 如何摆脱结构的数据成员之间的填充字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3277842/

相关文章:

c++ - 如何动态地在参数化构造函数中?

C++ 对二进制表达式 ('IOperand *' 和 'IOperand *' 的无效操作数)

可以从类中设置的 C++ 只读结构?

创建 I2C 设备驱动程序结构设置

node.js - Node 的超时功能?

c++ - 如何将值初始化为 vector 中声明的对象?

c++ - 将矩阵字段设置为 Matlab 结构

c - 结构节点释放

具有数组/向量性能特征的 Scala 流

json - 转换文件完整内容nodejs