我把整个代码放在不同的文件中(.h和.c文件)
typedef unsigned char ubyte;
typedef unsigned int uint;
#include<stdbool.h>
typedef struct Cube {
ubyte n;
ubyte e;
ubyte s;
ubyte w;
} Cube;
typedef struct Piece {
Cube c;
bool is_main;
char offset_n;
char offset_s;
} Piece;
typedef struct Block {
ubyte total;
Piece* pieces;
} Block;
Block *block_create(uint nb_pieces) {
Block *block = malloc(sizeof(Block) + (sizeof(Piece) * nb_pieces));
block->pieces = (Piece *) (&block + sizeof(Block));
return block;
}我只是想知道这一行代码:block->pieces = (&block + sizeof(Block));是否是,始终是安全的。我的意思是:我们能确定,在sizeof(Piece)之后,我们就会有精确的(sizeof(Piece) * nb_pieces)吗?我们确定永远不会出现对齐问题(即如果64位对齐,sizeof(Block)的内存将小于8字节,block->pieces不应该指向精确的sizeof(Block),而是"sizeof(Block) 64位对齐“)。
希望我说得够清楚。
发布于 2022-03-12 16:36:54
首先,这不是您所期望的,而且有多种原因:
block->pieces = (&block + sizeof(Block));首先,&block是变量block的地址,而不是block的内容,并且具有block **类型。最多,您可以安全地添加1这个指针值,因为任何更多的指针都会在这个变量结束后创建一个指针,该指针无效。
因此,您需要将&block更改为block。这仍然不能达到预期的效果,因为指针算法会将原始地址增加到对象大小的倍数。因此,向其中添加sizeof(Block)并不是向上移动1个数组元素,而是向上移动sizeof(Block)数组元素。
要解决这个问题,您需要block + 1。现在你需要开始担心对齐了。要正确地对齐Pieces数组,需要检查_Alignof(Block)和_Alignof(Piece)是否相同。如果没有,则需要添加填充字节:
int padding = 0;
if (_Alignof(Block) % _Alignof(Piece) != 0) {
padding = _Alignof(Piece) - (_Alignof(Block) % _Alignof(Piece));
}
Block *block = malloc(sizeof(Block) + padding + (sizeof(Piece) * nb_pieces));
block->pieces = (Piece *)((char *)(block + 1) + padding);当然,您可以通过使pieces成员成为一个灵活的数组成员来避免这一切。
typedef struct Block {
ubyte total;
Piece pieces[];
} Block;而分配本身就足够了。
https://stackoverflow.com/questions/71451305
复制相似问题