如何在一个内存块中连接多个结构体?
How to Concatenate Multiple Structs within One Block of Memory?
我正在用标准 C 编写程序。我有许多已定义的结构,它们的大小各不相同:
typedef struct innerDataStruct{
int d1, d2;
}dataStruct;
// - - - - - - - - - - - - - -
typedef struct structA{
dataStruct data;
}hdrA;
typedef struct structB{
int d1, d2, d3;
}hdrB;
typedef struct structC{
int d1;
}hdrC;
我需要分配并填充一个 hdrA、hdrB 和 hdrC 结构,然后将它们连接成一大块内存。另外,我需要在堆上分配我所有的内存,而不是本地堆栈。
(我想我可以遍历每个结构并一个一个地复制每个元素,但这很痛苦。此外,这些结构可能会在以后修改,我不想如果发生这种情况,请重写我的代码。最好将整个结构直接复制到大块内存中。)
这是我认为可行的解决方案:
int* makeBigChunk( hdrA* A, hdrB* B, hdrC* C ){
size_t size = sizeof( hdrA ) + sizeof( hdrB ) + sizeof( hdrC );
int* bigChunk = malloc( size );
bzero( bigChunk, size );
int iter = 0;
memcpy( bigChunk+iter, A, sizeof( hdrA ) );
iter += sizeof( hdrA );
memcpy( bigChunk+iter, B, sizeof( hdrB ) );
iter += sizeof( hdrB );
memcpy( bigChunk+iter, C, sizeof( hdrC ) );
return bigChunk;
}
void printBigChunk( int* bc ){
size_t size = sizeof( hdrA ) + sizeof( hdrB ) + sizeof( hdrC );
printf("Big Chunk of Memory is :: %ld bytes:\n", size);
int i = 0;
for(; i < size; i++){
printf("%d ", *(bc+i));
}
printf("\n");
}
int main( int argc, char **argv ){
hdrA* AAA = malloc( sizeof(hdrA) );
hdrB* BBB = malloc( sizeof(hdrB) );
hdrC* CCC = malloc( sizeof(hdrC) );
AAA->data.d1 = 1; AAA->data.d2 = 2;
BBB->d1 = 10; BBB->d2 = 20; BBB->d3 = 30;
CCC->d1 = 100;
int* bigChunk = makeBigChunk( AAA, BBB, CCC );
printBigChunk( bigChunk );
free( bigChunk );
free( AAA );
free( BBB );
free( CCC );
printf("END OF PROGRAM.\n");
return 0;
}
我希望输出是这样的:
Big Chunk of Memory is :: 6 bytes:
1 2 10 20 30 100
END OF PROGRAM.
但是实际的输出并不是很鼓舞人心:
Big Chunk of Memory is :: 24 bytes:
1 2 0 0 0 0 1041 0 540155953 540024880 540024880 825503793 891301920 892416052 859126069 808727840 942944816 891301944 842018868 808990772 892483616 926101557 941634361 808661305
END OF PROGRAM.
所以我猜我在这里有两个问题:首先,当我 memcpy()
每个结构进入 bigChunk
时,我使用这个迭代系统:
int iter = 0;
memcpy( bigChunk+iter, A, sizeof( hdrA ) );
iter += sizeof( hdrA );
memcpy( bigChunk+iter, B, sizeof( hdrB ) );
iter += sizeof( hdrB );
memcpy( bigChunk+iter, C, sizeof( hdrC ) );
我写的时候觉得很聪明,但显然有些地方不对。但我不确定是什么。其次,我认为我的 printBigChunk()
函数正确地迭代了 bigChunk
。它显然多算了我需要的实际内存量。
有人看到我哪里错了吗?这是结构填充问题还是什么?不幸的是,我不允许更改结构。谢谢!
编辑:This post 是我想做的,但不完全是。而且我无法使它适应我的代码。
请记住,对于任何指针或数组 p
和索引 i
,表达式 *(p + i)
正好等于 p[i]
。由此得出 p + i
等于 &p[i]
.
这意味着在您的示例中 bigChunk+iter
将与 &bigChunk[iter]
相同。由于 bigChunk
是 int *
,编译器会将 bigChunk
视为 int
的数组,而不是字节数组.
对于第二个结构,您将把它复制到 bigChunk[8]
(假设没有填充),它位于 32 的 byte-offset(假设大小of 4
for int
) 从内存开始。这远远超出了第二个结构的偏移量(它的 byte-offset 应该是 8
)。
改为使用 char *
作为 bigChunk
的类型,使其成为“字节数组”。
我正在用标准 C 编写程序。我有许多已定义的结构,它们的大小各不相同:
typedef struct innerDataStruct{
int d1, d2;
}dataStruct;
// - - - - - - - - - - - - - -
typedef struct structA{
dataStruct data;
}hdrA;
typedef struct structB{
int d1, d2, d3;
}hdrB;
typedef struct structC{
int d1;
}hdrC;
我需要分配并填充一个 hdrA、hdrB 和 hdrC 结构,然后将它们连接成一大块内存。另外,我需要在堆上分配我所有的内存,而不是本地堆栈。
(我想我可以遍历每个结构并一个一个地复制每个元素,但这很痛苦。此外,这些结构可能会在以后修改,我不想如果发生这种情况,请重写我的代码。最好将整个结构直接复制到大块内存中。)
这是我认为可行的解决方案:
int* makeBigChunk( hdrA* A, hdrB* B, hdrC* C ){
size_t size = sizeof( hdrA ) + sizeof( hdrB ) + sizeof( hdrC );
int* bigChunk = malloc( size );
bzero( bigChunk, size );
int iter = 0;
memcpy( bigChunk+iter, A, sizeof( hdrA ) );
iter += sizeof( hdrA );
memcpy( bigChunk+iter, B, sizeof( hdrB ) );
iter += sizeof( hdrB );
memcpy( bigChunk+iter, C, sizeof( hdrC ) );
return bigChunk;
}
void printBigChunk( int* bc ){
size_t size = sizeof( hdrA ) + sizeof( hdrB ) + sizeof( hdrC );
printf("Big Chunk of Memory is :: %ld bytes:\n", size);
int i = 0;
for(; i < size; i++){
printf("%d ", *(bc+i));
}
printf("\n");
}
int main( int argc, char **argv ){
hdrA* AAA = malloc( sizeof(hdrA) );
hdrB* BBB = malloc( sizeof(hdrB) );
hdrC* CCC = malloc( sizeof(hdrC) );
AAA->data.d1 = 1; AAA->data.d2 = 2;
BBB->d1 = 10; BBB->d2 = 20; BBB->d3 = 30;
CCC->d1 = 100;
int* bigChunk = makeBigChunk( AAA, BBB, CCC );
printBigChunk( bigChunk );
free( bigChunk );
free( AAA );
free( BBB );
free( CCC );
printf("END OF PROGRAM.\n");
return 0;
}
我希望输出是这样的:
Big Chunk of Memory is :: 6 bytes:
1 2 10 20 30 100
END OF PROGRAM.
但是实际的输出并不是很鼓舞人心:
Big Chunk of Memory is :: 24 bytes:
1 2 0 0 0 0 1041 0 540155953 540024880 540024880 825503793 891301920 892416052 859126069 808727840 942944816 891301944 842018868 808990772 892483616 926101557 941634361 808661305
END OF PROGRAM.
所以我猜我在这里有两个问题:首先,当我 memcpy()
每个结构进入 bigChunk
时,我使用这个迭代系统:
int iter = 0;
memcpy( bigChunk+iter, A, sizeof( hdrA ) );
iter += sizeof( hdrA );
memcpy( bigChunk+iter, B, sizeof( hdrB ) );
iter += sizeof( hdrB );
memcpy( bigChunk+iter, C, sizeof( hdrC ) );
我写的时候觉得很聪明,但显然有些地方不对。但我不确定是什么。其次,我认为我的 printBigChunk()
函数正确地迭代了 bigChunk
。它显然多算了我需要的实际内存量。
有人看到我哪里错了吗?这是结构填充问题还是什么?不幸的是,我不允许更改结构。谢谢!
编辑:This post 是我想做的,但不完全是。而且我无法使它适应我的代码。
请记住,对于任何指针或数组 p
和索引 i
,表达式 *(p + i)
正好等于 p[i]
。由此得出 p + i
等于 &p[i]
.
这意味着在您的示例中 bigChunk+iter
将与 &bigChunk[iter]
相同。由于 bigChunk
是 int *
,编译器会将 bigChunk
视为 int
的数组,而不是字节数组.
对于第二个结构,您将把它复制到 bigChunk[8]
(假设没有填充),它位于 32 的 byte-offset(假设大小of 4
for int
) 从内存开始。这远远超出了第二个结构的偏移量(它的 byte-offset 应该是 8
)。
改为使用 char *
作为 bigChunk
的类型,使其成为“字节数组”。