代码之家  ›  专栏  ›  技术社区  ›  David Ranieri

使用max_align_t存储字节块

  •  0
  • David Ranieri  · 技术社区  · 7 年前

    在里面 this thread 有人建议我使用 max_align_t 为了让任何类型的地址正确对齐,我最终创建了一个动态数组的实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stddef.h>
    
    struct vector {
        size_t capacity;
        size_t typesize;
        size_t size;
        max_align_t data[];
    };
    
    #define VECTOR(v) ((struct vector *)((unsigned char *)v - offsetof(struct vector, data)))
    
    static void *valloc(size_t typesize, size_t size)
    {
        struct vector *vector;
    
        vector = calloc(1, sizeof(*vector) + typesize * size);
        if (vector == NULL) {
            return NULL;
        }
        vector->typesize = typesize;
        vector->capacity = size;
        vector->size = 0;
        return vector->data;
    }
    
    static void vfree(void *data, void (*func)(void *))
    {
        struct vector *vector = VECTOR(data);
    
        if (func != NULL) {
            for (size_t iter = 0; iter < vector->size; iter++) {
                func((unsigned char *)vector->data + vector->typesize * iter);
            }
        }
        free(vector);
    }
    
    static void *vadd(void *data)
    {
        struct vector *vector = VECTOR(data);
        struct vector *new;
        size_t capacity;
    
        if (vector->size >= vector->capacity) {
            capacity = vector->capacity * 2;
            new = realloc(vector, sizeof(*vector) + vector->typesize * capacity);
            if (new == NULL) {
                return NULL;
            }
            new->capacity = capacity;
            new->size++;
            return new->data;
        }
        vector->size++;
        return vector->data;
    }
    
    static size_t vsize(void *data)
    {
        return VECTOR(data)->size;
    }
    
    static void vsort(void *data, int (*comp)(const void *, const void *))
    {
        struct vector *vector = VECTOR(data);
    
        if (vector->size > 1) {
            qsort(vector->data, vector->size, vector->typesize, comp);
        }
    }
    
    static char *vgetline(FILE *file)
    {
        char *data = valloc(sizeof(char), 32);
        size_t i = 0;
        int c;
    
        while (((c = fgetc(file)) != '\n') && (c != EOF)) {
            data = vadd(data);
            data[i++] = (char)c;
        }
        data = vadd(data);
        data[i] = '\0';
        return data;
    }
    
    struct data {
        int key;
        char *value;
    };
    
    static int comp_data(const void *pa, const void *pb)
    {
        const struct data *a = pa;
        const struct data *b = pb;
    
        return strcmp(a->value, b->value);
    }
    
    static void free_data(void *ptr)
    {
        struct data *data = ptr;
    
        vfree(data->value, NULL);
    }
    
    int main(void)
    {
        struct data *data;
    
        data = valloc(sizeof(struct data), 1);
        if (data == NULL) {
            perror("valloc");
            exit(EXIT_FAILURE);
        }
        for (size_t i = 0; i < 5; i++) {
            data = vadd(data);
            if (data == NULL) {
                perror("vadd");
                exit(EXIT_FAILURE);
            }
            data[i].value = vgetline(stdin);
            data[i].key = (int)vsize(data[i].value);
        }
        vsort(data, comp_data);
        for (size_t i = 0; i < vsize(data); i++) {
            printf("%d %s\n", data[i].key, data[i].value);
        }
        vfree(data, free_data);
        return 0;
    }
    

    但我不确定我能不能用 最大对齐 要存储字节块,请执行以下操作:

    struct vector {
        size_t capacity;
        size_t typesize;
        size_t size;
        max_align_t data[]; // Used to store any array,
                            // for example an array of 127 chars
    }; 
    

    它是否打破了数组规则中最后一个元素之后的一个?

    0 回复  |  直到 7 年前
        1
  •  2
  •   chux    7 年前

    它是否打破了数组规则中最后一个元素之后的一个?

    使用 max_align_t 存储一块字节

    OP的问题并不特别,因为它使用了 柔性阵列成员 .

    作为特例,结构的最后一个元素。。。数组类型不完整;这就是所谓的灵活数组成员。。。然而,当。(或->)运算符的左操作数是(指向)一个具有灵活数组成员的结构,右操作数将该成员命名为它 行为就像该成员被替换为最长的数组(具有相同的元素类型) ...

    这与像访问另一种类型的内存或数组一样访问任何分配的内存或数组是同一个问题。

    这个 转变 从…起 max_align_t * char * void * 当对齐正确时,定义良好。

    指向对象类型的指针可以转换为指向不同对象类型的指针。如果结果指针与引用的类型未正确对齐,则行为未定义。C11dr§6.3.2.3 7

    所有代码中的已审核访问都不会尝试在“仿佛”数组之外进行访问。