如何去除结构的数据成员之间的填充字节 [英] How to get rid of padding bytes between data members of a struct

查看:210
本文介绍了如何去除结构的数据成员之间的填充字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个二进制文件与消息,我想使用structs适当的字节在正确的变量。在我的示例中,我使用两种类型的消息:Tmessage和Amessage。

I have a binary file with "messages" and I am trying to fit the bytes inside the right variable using structs. In my example I used two types of messages: Tmessage and 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


$ b b

程序将字节放在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)

The program places the bytes inside the Tmessage struct correctly. (0 5 54 0 0 62 72)
However, something occurs while parses 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包含53到BuySellIndicator,然后其他变量不正确。

The Lenght, MessageType and Timestamp are correct but OrderReferenceNumber contains the "53" byte which belongs to BuySellIndicator and then the other variable are incorrect.

正确的消息输出应该是:

长度:1c 0

消息类型:41

时间戳:40 42 f 0

OrderReferenceNumber:76 2f 4 0 0 0 0 0

BuySellIndicator:53

股票:e8 3 0 0

股票:53 50 59 20 20 20

价格:d0 5 11 0

The correct A message output should be:
Length: 1c 0
Message type: 41
Timestamp: 40 42 f 0
OrderReferenceNumber: 76 2f 4 0 0 0 0 0
BuySellIndicator: 53
Shares: e8 3 0 0
Stock: 53 50 59 20 20 20
Price: d0 5 11 0

这两个问题:
a)为什么OrderReferenceNumber包含53字节?
b)我认为char Stock [6]不工作,因为Share的字节和Price的字节之间有6个以上的字节。如何将6个字节适合到char向量或字符串?

The 2 questions: a) Why the OrderReferenceNumber contains the "53" byte? b) I think that "char Stock[6]" does not work, because between Share's bytes and Price's bytes there are more than 6 bytes. How can I fit the 6 bytes into the char vector or string?

注意:我知道我必须交换字节,因为二进制数据是以big-endian。这就是为什么股票不应该交换。
非常感谢您的帮助!请考虑,

Note: I am aware that I have to swap the bytes because the binary data comes in big-endian. That is why "Stock" should not be swapped. Thank you very much for your help! Kind regards,

推荐答案

编译器可能在结构的成员之间插入填充字节。一种方法,你可以绕过这是使用pragma pack。注意,这是非标准的,但它适用于g ++和可视化C ++。

The compiler is probably inserting pad bytes between members of your struct. One way you can get around this is to use pragma pack. Note that this is non-standard, but it works on g++ and visual C++.

#pragma pack (push, 1)
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;
};
#pragma pack (pop)

上面的代码中发生了什么:pragma pack告诉编译器你不希望它插入填充以使它将执行对结构的成员的对齐访问。 push / pop的东西是这样的,你可以有嵌套的#pragma包(例如,当包括头文件),并有一个方法,回到以前设置包选项。

What's going on in the code above is: the pragma pack tells the compiler you don't want it to insert padding to make it so that it'll be performing aligned access to members of the struct. the push/pop thing is so you can have nested #pragma packs (for example, when including header files) and have a way to go back to the previously set pack options.

看到MSDN的解释,可能比我可以给的更好。
http://msdn.microsoft.com /en-us/library/2e70t5y1%28VS.80%29.aspx

See MSDN for an explanation that's probably better than the one I could give. http://msdn.microsoft.com/en-us/library/2e70t5y1%28VS.80%29.aspx

这篇关于如何去除结构的数据成员之间的填充字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆