使用 max_align_t 存储一大块字节 [英] Using max_align_t to store a chunk of bytes

查看:38
本文介绍了使用 max_align_t 存储一大块字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个线程中,有人建议我使用 max_align_t 以正确获取地址对齐任何类型,我最终创建了一个动态数组的实现:

In this thread I was suggested to use max_align_t in order to get an address properly aligned for any type, I end up creating this implementation of a dynamic array:

#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;
}

但我不确定是否可以使用 max_align_t 来存储一大块字节:

But I'm not sure if I can use max_align_t to store a chunk of bytes:

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
}; 

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

Does it break the one past the last element of an array rule?

推荐答案

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

Does it break the one past the last element of an array rule?

没有

使用max_align_t来存储一个字节块

OP 的问题并不特别,因为它使用了一个灵活的数组成员.

OP's issue is not special because it uses a flexible array member.

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

As a special case, the last element of a structure ... have an incomplete array type; this is called a flexible array member. ... However, when a . (or ->) operator has a left operand that is (a pointer to) a structure with a flexible array member and the right operand names that member, it behaves as if that member were replaced with the longest array (with the same element type) ...

这与访问任何已分配的内存或一种类型的数组是相同的问题,就好像它是另一种类型一样.

It is the same issue as accessing any allocated memory or array of one type as if it was another type.

max_align_t *char *void *转换在正确对齐时被很好地定义.

The conversion from max_align_t * to char * to void * is well defined when alignment is done right.

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

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. C11dr §6.3.2.3 7

所有在代码中查看的访问都不会尝试在as if"数组之外进行访问.

All reviewed accessing in code do not attempt to access outside the "as if" array.

这篇关于使用 max_align_t 存储一大块字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆