malloc + size_t * 3的地址是否适合任何类型? [英] Is the address of malloc + size_t * 3 aligned for any type?

查看:50
本文介绍了malloc + size_t * 3的地址是否适合任何类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一种动态数组(向量),但不是将数据(通常是void *)嵌入到struct vector中,而是为struct vector +字节块保留了空间,一个使用size_t的数组的示例:

I'm builing a kind of dynamic array (vector), but instead of embedding the data (typically void *) into a struct vector, I'm reserving space for a struct vector + a chunk of bytes, an example using an array of size_t's:

#include <stdio.h>
#include <stdlib.h>

struct vector {
    size_t capacity;
    size_t typesize;
    size_t size;
};

#define VECTOR(v) ((struct vector *)((unsigned char *)v - sizeof(struct vector)))

static void *valloc(size_t typesize, size_t size)
{
    struct vector *vector;
    unsigned char *data;

    data = calloc(1, sizeof(*vector) + typesize * size);
    if (data == NULL) {
        return NULL;
    }
    vector = (struct vector *)data;
    vector->typesize = typesize;
    vector->capacity = size;
    vector->size = 0;
    return data + sizeof(*vector);
}

static void *vadd(void *data)
{
    struct vector *vector = VECTOR(data);
    unsigned char *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;
        }
        vector = (struct vector *)new;
        vector->capacity = capacity;
        vector->size++;
        return new + sizeof(*vector);
    }
    vector->size++;
    return data;
}

static size_t vsize(void *data)
{
    return VECTOR(data)->size;
}

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(*(void **)((unsigned char *)data + iter * vector->typesize));
        }
    }
    free(vector);
}

int main(void)
{
    size_t *data;

    data = valloc(sizeof(size_t), 1);
    if (data == NULL) {
        perror("valloc");
        exit(EXIT_FAILURE);
    }
    for (size_t i = 0; i < 10; i++) {
        data = vadd(data);
        if (data == NULL) {
            perror("vadd");
            exit(EXIT_FAILURE);
        }
        data[i] = i;
    }
    for (size_t i = 0; i < vsize(data); i++) {
        printf("%zu\n", data[i]);
    }
    vfree(data, NULL);
    return 0;
}

问题是:malloc(void *)的结果的地址+ struct的大小是否适合任何类型?该代码的行为定义是否正确?

The question is: Is the address of the result of malloc (void *) + the size of the struct well aligned for any type? Is the behaviour of this code well defined?

推荐答案

malloc + size_t * 3的地址是否适合任何类型?

Is the address of malloc + size_t * 3 aligned for any type?

不,不一定.

通过使前缀数据也为基本对准来确定基本对准.

Make certain of fundamental alignment by making the prefix data also of fundamental alignment.

一种方法是使用struct vectormax_align_t中的union. union uvector的大小将是基本排列的倍数.

One way is to use of union of struct vector and max_align_t. The size of union uvector will be a multiple of the fundamental alignment.

max_align_t 这是一种对象类型,其对齐方式与实现所支持的对齐方式一样大 在所有情况下;

max_align_t which is an object type whose alignment is as great as is supported by the implementation in all contexts;

union uvector {
  max_align_t a;
  struct vector {
    size_t capacity;
    size_t typesize;
    size_t size;
  } v;
};

union uvector *uvector;
unsigned char *data;

data = calloc(1, sizeof *uvector ...
...
return data + sizeof *uvector;


答案效率低下-在另一个答案中进行了重新设计.


Answer has some inefficiencies - Reworked in another answer..

这篇关于malloc + size_t * 3的地址是否适合任何类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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