我发布了这个主题earlier,但现在我有一个更具体的问题/问题。
这是我的代码:
#include <cstdlib>
#include <iostream>
typedef struct{
unsigned int h;
unsigned int b[];
unsigned int t;
} pkt;
int main(){
unsigned int* arr = (unsigned int*) malloc(sizeof(int) * 10);
arr[0] = 0xafbb0000;
arr[1] = 0xafbb0001;
arr[2] = 0xafbb0011;
arr[3] = 0xafbb0111;
arr[4] = 0xafbb1111;
arr[5] = 0xafbc0000;
arr[6] = 0xafbc0001;
arr[7] = 0xafbc0011;
arr[8] = 0xafbc0111;
arr[9] = 0xafbc1111;
pkt* p = (pkt*) malloc(sizeof(int)*13);
p->h = 0x0905006a;
int counter;
这是我得到的 for(counter = 0; counter&lt; 10; counter ++) p-> b [counter] = arr [counter];
p->t = 0x55555555;
std::cout << "header is \n" << p->h << std::endl;
std::cout << "body is" << std::endl;
for(counter=0; counter < 10;++counter)
std::cout << std::hex << *((p->b)+counter) << std::endl;
std::cout << "trailer is \n" << p->t << std::endl;
}
这是我得到的
header is
151322730
body is
55555555
afbb0001
afbb0011
afbb0111
afbb1111
afbc0000
afbc0001
afbc0011
afbc0111
afbc1111
trailer is
55555555
*(p-> b)被预告片取代!如果我删除了我分配预告片的行,即p-> t = 0x55555555;那么预告片和p-> b是相同的(afbb0000)。
所以我的问题是,我怎样才能保持结构的顶部定义,并让这个数据包正常运行。
编辑:
我应该更清楚。我为网络应用程序写这个,所以我必须制作一个输出按照这个顺序排序的数据包,我通过写入文件并进行十六进制转储来测试它。所以我的问题是:
如何制作带有标题,可变大小的正文和预告片的数据包始终具有此顺序?我能想到的唯一两个解决方案是拥有许多不同的结构,或者有一个向量。
也就是说,我可以在哪里结构
typedef struct{
unsigned int h;
unsigned int b[12];
unsigned int t;
} pkt1;
typedef struct{
unsigned int h;
unsigned int b[102];
unsigned int t;
} pkt2;
etc
或者我可以做
std::vector<unsigned int> pkt (12);
pkt[0] = header;
pkt[1] = data;
...
pkt[2]= data;
pkt[11] = trailer;
我真的不喜欢这两种解决方案。还有更好的方法吗?
此外,这是一个单独的问题,我将不得不做同样的事情来接收数据。做一些事情就像把数据块投射到矢量一样明智吗?我将以无效*的形式接收数据,我将知道最大长度。
答案 0 :(得分:6)
尝试更新结构,然后添加以下内容:
typedef struct{
unsigned int h;
unsigned int* b;
unsigned int t;
} pkt;
...
...
pkt p;
p->b = arr
这是一个关于它正在做什么的视觉例子......
|----------------------|
| header |
|----------------------|
| B int* | ------- p->b = arr
|----------------------| |
| trailer | |
|----------------------| v
|----------------------|
arr | |
| B items [0 ... N] |
| |
|----------------------|
如果你想变得棘手,你可以做这样的事情......
|----------------------|
| header |
|----------------------|
| B int* | ------- (= to memory address after trailer)
|----------------------| |
| trailer | |
|----------------------| |
| | <-------
| B items [0 ... N] |
| |
|----------------------|
以下是后者的工作版本:
#include "stdlib.h"
#include "stdio.h"
#include "malloc.h"
typedef struct{
unsigned int h;
unsigned int* b;
unsigned int t;
} pkt;
int main(){
pkt* p = (pkt*) malloc( sizeof(pkt) + sizeof(int)*10);
p->h = 0x0905006a;
p->b = &(p->t)+1;
p->t = 0x55555555;
p->b[0] = 0xafbb0000;
p->b[1] = 0xafbb0001;
p->b[2] = 0xafbb0011;
p->b[3] = 0xafbb0111;
p->b[4] = 0xafbb1111;
p->b[5] = 0xafbc0000;
p->b[6] = 0xafbc0001;
p->b[7] = 0xafbc0011;
p->b[8] = 0xafbc0111;
p->b[9] = 0xafbc1111;
int counter;
printf( "header is \n" );
printf( "%0x\n", p->h);
printf( "body is\n" );
for(counter=0; counter < 10;++counter)
printf( "%0x\n", (p->b)[counter]);
printf( "trailer is\n" );
printf( "%0x\n", p->t );
}
答案 1 :(得分:4)
基本上,你不能。我很惊讶这甚至可以编译。您只允许将没有指定大小的数组作为结构的最后一个元素,因为结构在C / C ++中的基本方式。
问题是编译器必须知道b []有多大才能知道在struct中找到t的位置。通常它通过查看数组大小来实现。由于你没有传递一个大小,你的编译器显然将它视为零,这意味着b []和t实际上在内存中的相同位置!你需要在struct声明中指定b []的大小,或者你需要在b []之前移动t。
答案 2 :(得分:2)
C ++解决方案:
#include <iostream>
using namespace std;
class Packet
{
public:
Packet (int body_size) :
m_body_size (body_size)
{
m_data = new int [m_body_size + 2];
}
~Packet ()
{
delete [] m_data;
m_data = 0;
}
int &Header ()
{
return m_data [0];
}
int &Trailer ()
{
return m_data [m_body_size + 1];
}
int Size ()
{
return m_body_size;
}
int *Data ()
{
return m_data;
}
int &operator [] (int index)
{
return m_data [index + 1];
}
// helper to write class data to an output stream
friend ostream &operator << (ostream &out, Packet &packet)
{
out << "Header = " << packet.Header () << endl;
out << "Data [" << packet.Size () << "]:" << endl;
for (int i = 0 ; i < packet.Size () ; ++i)
{
out << " [" << i << "] = 0x" << hex << packet [i] << endl;
}
out << "Trailer = " << packet.Trailer () << endl;
return out;
}
private:
int
m_body_size,
*m_data;
};
// simple test function for Packet class
int main ()
{
Packet
packet (10);
packet.Header () = 0x0905006a;
packet [0] = 0xafbb0000;
packet [1] = 0xafbb0001;
packet [2] = 0xafbb0011;
packet [3] = 0xafbb0111;
packet [4] = 0xafbb1111;
packet [5] = 0xafbc0000;
packet [6] = 0xafbc0001;
packet [7] = 0xafbc0011;
packet [8] = 0xafbc0111;
packet [9] = 0xafbc1111;
packet.Trailer () = 0x55555555;
cout << packet;
}
我没有把错误检查或const访问器,你可以检查数组访问。接收数据非常简单:
Packet Read (stream in)
{
get size of packet (exluding header/trailer)
packet = new Packet (size)
in.read (packet.Data, size + 2)
return packet
}
答案 3 :(得分:1)
如果你改变了
typedef struct{
unsigned int h;
unsigned int b[];
unsigned int t;
} pkt;
要
typedef struct{
unsigned int h;
unsigned int *b;
unsigned int t;
} pkt;
我相信它会奏效。这样,b
和t
将各自占用自己的空间,而不是相同的空间。您还需要将malloc(sizeof(int) * 13);
更改为malloc(sizeof(pkt));
- malloc()
的大小将保持不变,并且您需要malloc()
两次 - struct
一次},和b
中的数组一次。当然,无论如何你已经这样做了,但这样你就不会浪费堆空间。
如果您想使用b[]
代替*b
(并且有正当理由),您需要将其放在最后。抱歉。这就是黑客的工作方式。
答案 4 :(得分:1)
当你在struct中声明unsigned int b []时,它没有为它分配任何空间。所以当您取消引用结构指针时,pkt.b和pkt.t是相同的位置。你可以使b []成为结构中的最后一个字段。
但是,如果您想要关注b,那么您可以尝试以下C示例:
#include <stdio.h>
#include <malloc.h>
#define PKT_STRUCT(size) struct{unsigned int h;unsigned int b[size];unsigned int t;}
int main(void)
{
PKT_STRUCT(10) *pkt = malloc(sizeof(PKT_STRUCT(10)));
pkt->h = 0x0905006a;
pkt->b[0] = 0xafbb0000;
pkt->b[1] = 0xafbb0001;
pkt->b[2] = 0xafbb0011;
pkt->b[3] = 0xafbb0111;
pkt->b[4] = 0xafbb1111;
pkt->b[5] = 0xafbc0000;
pkt->b[6] = 0xafbc0001;
pkt->b[7] = 0xafbc0011;
pkt->b[8] = 0xafbc0111;
pkt->b[9] = 0xafbc1111;
pkt->t = 0x55555555;
printf("Header: %x\n", pkt->h);
printf("Body:\n");
int i;
for(i=0; i<10; ++i)
printf("%x\n", pkt->b[i]);
printf("Tail: %x\n", pkt->t);
return 0;
}
如果您正在使用已打包的数据,这可能很有用。
此外,您可以使用不同数据包大小/结构的并集。
答案 5 :(得分:1)
如果你已经标记了问题C ++,你总是可以使用vector&lt; int&gt;而不是int []。更好的是,让pkt成为一个类并隐藏客户端的内部表示。然后,您将拥有标题和预告片的访问者以及正文的索引器。