arrays - 如何处理 C 中动态数组的标头对齐
问题描述
我正在用 C 实现一个任意类型的动态数组。该实现通过在数组数据之前分配一个标头来工作:
typedef struct
{
unsigned char* begin; // Pointer to data
unsigned char* end; // Pointer to last element
size_t typeSize; // Size of type
size_t capacity; // Capacity of array (not number of elements in array)
} dynamicArr;
#define dynamicArr_ConstructBase(dest, src, newCapacity) \
dest = src; \
dest->capacity = newCapacity; \
dest->begin = (unsigned char*)dest + sizeof *dest
#define dynamicArr_Construct(dest, src, newCapacity, currSize, typeSize) \
dynamicArr_ConstructBase(dest, src, newCapacity); \
dest->end = dest->begin + typeSize * (currSize)
#define dynamicArr_Header(arr) ((dynamicArr*)((unsigned char*)(arr) - sizeof(dynamicArr)))
static inline size_t dynamicArr_Size(dynamicArr* arr)
{
return (arr->end - arr->begin) / arr->typeSize;
}
#define dynamicArr_Create(typename, arr) typename* arr = (typename*)dynamicArr_Create_(sizeof(typename))
static inline unsigned char* dynamicArr_Create_(size_t typeSize)
{
dynamicArr* dynArr;
void* tmp = malloc(sizeof * dynArr + typeSize * 10);
if (!tmp) return NULL;
dynArr = tmp;
dynArr->begin = (unsigned char*)dynArr + sizeof * dynArr;
dynArr->end = dynArr->begin;
dynArr->capacity = 10;
dynArr->typeSize = typeSize;
return dynArr->begin;
}
#define dynamicArr_Free(arr) free(dynamicArr_Header(arr))
#define dynamicArr_Push(arr, item) \
do \
{ \
if (arr) \
{ \
dynamicArr* header = dynamicArr_Header(arr); \
if (header->typeSize && header->typeSize == sizeof item) \
{ \
size_t arrSize = dynamicArr_Size(header); \
if (arrSize == header->capacity) \
{ \
size_t newCapacity = (size_t)(header->capacity * 1.5f); \
if (newCapacity == header->capacity) ++newCapacity; \
void* tmp = realloc(header, sizeof(dynamicArr) + header->typeSize * newCapacity); \
if (tmp) \
{ \
dynamicArr_Construct(header, tmp, newCapacity, arrSize, header->typeSize); \
*((void**)&(arr)) = header->begin; \
arr[arrSize] = item; \
header->end += header->typeSize; \
} \
else \
{ \
free(header); \
arr = NULL; \
} \
} \
else \
{ \
arr[arrSize] = item; \
header->end += header->typeSize; \
} \
} \
} \
} while(0)
使用示例:
void Func()
{
dynamicArr_Create(int, intArr);
dynamicArr_Push(intArr, 10);
printf("%i\n", intArr[0]);
dynamicArr_Free(intArr);
}
这样做的问题是,我认为这是未定义的行为,因为如果编译器选择使用对齐指令作为数组的项目,则在标头之后可能未对齐。
有没有办法保证项目的对齐?
我已经研究过使用灵活的数组成员,但是我不确定如何实现它以使其适用于任意类型。
例如,我可以像这样声明标题:
#define dynamicArr_Header(type) \
struct \
{ \
size_t typeSize; \
size_t capacity; \
type data[]; \
}
但是,如果我要在代码中使用它,我的编译器会警告我'=': incompatible types - from '*' to '*'
。
导致警告的示例:
dynamicArr_Header(int)* A = malloc(sizeof(dynamicArr_Header(int)));
dynamicArr_Header(int)* B = A; //Causes warning
这样做危险吗?这是因为匿名结构真的不是同一类型,还是会导致更多问题(例如我是否可以保证编译器以相同的方式填充和打包这些结构)?
灵活的数组成员方法的另一个“问题”是我必须传递头指针,这与之前的方法不同,我只能提供指向数据的指针。我知道使用灵活的数组版本可以:
int* pntrToIntArr = &header->data[0];
但是我希望将标头抽象出来,但是如果我提供指向数据数组的指针,我将如何取回标头?我可以(dynamicArr_Header(int)*)((unsigned char*)pntrToIntArr - sizeof(dynamicArr_Header(int)))
吗?
如果不违反严格的混叠/对齐规则,我在 C 中所做的事情是不可能的吗?我知道我可能用指针语义打破了很多严格的别名规则。
解决方案
推荐阅读
- python - 遍历嵌套的json对象并使用python获取表中的值
- javascript - 您如何在 Chakra-UI 输入中按 Enter 键提交?
- java - 如何选择pdf文件android studio
- node.js - Rocky Linux 8:NodeJS 的 DH 关键配置问题
- amazon-web-services - 全局表上用于 DynamoDB 中事务写入的总 rWCU
- angular - 在 Azure 应用服务上使用 ASP.NET Core 配置 Angular
- java - 如何从 Scala 程序调用 Java 中定义的方法?
- javascript - 搜索功能在下拉列表中不起作用
- javascript - 令牌值未定义尝试为我的登录页面请求 API 和身份验证
- python-3.x - 从二进制 8 位图像访问 LSB 和 MSB