我正在编写一个函数,其中我需要多次调用Malloc来动态地为非常小的数组(如4-5个整数)分配内存.组合和长度在运行时确定).这些数组用于存储不同类型的数据类型.因此,我想要分配一个大内存,并将其用于所有类型.这就是我想要做的.

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


int main() {
    
    size_t n_char = 4, n_float =4 ; /* these are not fixed. 
                                    I set this just for demonstrative purposes,
                                    n_char and n_float value are determined
                                    during runtime */
    
    char * a = malloc( n_char*sizeof(char) + n_float*sizeof(float) ); /* Allocating for 4 ints and 4 chars*/
    
    for (int i=0; i<4 ; ++i) a[i] = 'a' ; 
    
    float *b = (void *)(a+4) ; /* can we cast this pointer in this way ?*/
    
    for (int i=0; i<4 ; ++i) b[i] = 1.0f ;  
    
    for (int i=0; i<4 ; ++i) printf("%c" , a[i]) ;
    
    printf("\n");
    
    for (int i=0; i<4 ; ++i) printf("%f  " , (double)b[i]) ;
    
    printf("\n");

    return 0;
}

我现在很困惑,这是一种允许的好做法吗?

推荐答案

这不一定是一个好的做法,因为您不仅需要关心b的大小,还需要关心它的alignment requirements.假设您只需要2个字符,并且您使用了下面的代码,那么您的浮点数将在所有当前通用的平台上不正确地对齐.

如果您知道编译时的大小,只需分配一个 struct :

struct foo {
    char c[4];
    float f[4];
}

而编译器将负责其余的工作.否则,如果是动态的,并且您的字符数组是6个元素,则需要将6变为最接近的alignof(float)的倍数(最有可能是8).当然,您也需要分配足够的内存量,也就是说,不仅仅是数组元素的总和,还要考虑填充,也就是说,假设您分配了6个字符、6个浮点数,那么probably最终将得到6个字符、2个填充字节、6*4个浮点数.

强制转换本身被认为是合法的,指针算法也是如此,因为所有这些都指向一个没有有效类型的已分配array.


另一种不用担心alignof的方法是将101数组放在第一位-alignof(char)将是1,因此您总是可以将它们尽可能紧密地打包在一起.

C++相关问答推荐

C/C++中的状态库

为什么双重打印与C中的float具有不同的大小时具有相同的值?

GCC预处理宏和#杂注GCC展开

将整数的.csv文件解析为C语言中的二维数组

在C中将通用字符名称转换为UTF-8

GCC不顾-fno-Builtin-SINCOS旗帜向SINCOS发出呼唤

对于C中给定数组中的每个查询,如何正确编码以输出给定索引范围(1到N)中所有数字的总和?

在另一个函数中使用realloc和指针指向指针

Fprintf正在写入多个 struct 成员,并且数据过剩

如何将两个uint32_t值交织成一个uint64_t?

将非连续物理内存映射到用户空间

宏观;S C调深度

如何在不更改格式说明符的情况下同时支持双精度和长双精度?

C程序printf在getchar while循环后不工作

gdb - 你能找到持有内部 glibc 锁的线程吗?

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

GDB 跳过动态加载器代码

多行表达式:C 编译器如何处理换行符?

Rust 的 (void) 变量替代品

在 C 中有效返回多个值