微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何处理 C

如何解决如何处理 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,newCapacity,currSize,typeSize) \
dynamicArr_ConstructBase(dest,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,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);
}

这个问题是我认为这是未定义的行为,因为如果编译器选择使用对齐的指令作为标头之后的数组项,则可能未对齐。

有没有办法保证item的对齐?

我已经研究过使用灵活的数组成员,但是我不确定如何实现它以使其适用于任意类型。

例如,我可以像这样声明标题

#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 中做的事情是不可能的吗? 我知道我可能违反了很多指针语义的严格别名规则。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。