同一动态分配中的两种类型

时间:2019-07-17 05:25:58

标签: c malloc memory-alignment c89

ISO C90标准(或至少是我的草案)对此malloc和对齐方式进行了说明:

  

如果分配成功,则返回的指针将进行适当对齐,以便可以将其分配给指向任何类型对象的指针,然后将其用于在分配的空间中访问此类对象或此类对象的数组...

但是您可以将malloc返回的相同指针用于两种不同类型吗?例如,假设我知道sizeof(int) <= 2 * sizeof(short)。我能否为5 short分配足够的内存,并将前两个用作int,即以下代码是否保证能按预期工作?

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    void* data = malloc(5 * sizeof(short));
    short* short_array = data;
    int* int_ptr = data;
    if (!data) return EXIT_FAILURE;
    *int_ptr = 13943;
    short_array += 2; /* Skip over the int */
    short_array[0] = 7;
    short_array[1] = 238;
    short_array[2] = -123;
    printf("%d %d %d %d\n", *int_ptr, short_array[0], short_array[1], short_array[2]);
    free(data);
    return 0;
}

我已经尝试了这段代码,并且确实为我输出了13943 7 238 -123,但是我不确定它是否符合标准。


编辑:具体来说,我试图创建一个动态数组类型(可以是任何类型的数组),所以我要分配一种类型的数组,并使用该分配的开始作为指向的指针。包含数组长度和容量的标题。

要清楚,这大约是我在做什么:

size_t header_elements = (sizeof(ArrayHeader) + array_type_size - 1) / array_type_size); /* = ceil(sizeof(ArrayHeader) / array_type_size) */
void* data = malloc((header_elements + array_length) * array_type_size);
ArrayHeader* header = data;
void* array = (char*)data + header_elements * array_type_size;

因此,header指向分配的开始,实际的array偏移了存储在其中的类型的大小的倍数。

1 个答案:

答案 0 :(得分:1)

现在C90应该已经死了,安息。 C99,C11和C18行为是此处应考虑的行为。他们谈论了很多有效的类型。由于malloc分配的对象不是这样键入的,因此编译器将跟踪每个指针和内存区域的类型。

如果在前4个字节中写入int,则允许编译器将前4个字节中的数据类型视为int。如果您随后将短裤写入连续字节,则它们的有效类型将为short如果存储不重叠,则您的代码确定。

但是-注意:如果您将存储空间重叠,即将short写在int上,然后再读回int ,则所有投注均关闭。

最后,有一个避免歧义的好方法-使用struct类型。只是使用

struct two_types_in_one_malloc {
    int the_int;
    short the_shorts[3];
};