首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们可以使用单个malloc()块来表示两种不同的类型吗?

我们可以使用单个malloc()块来表示两种不同的类型吗?
EN

Stack Overflow用户
提问于 2022-08-07 09:27:13
回答 2查看 129关注 0票数 3

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

代码语言:javascript
复制
#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;
}

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-07 09:34:28

这不一定是一个很好的实践,因为您不仅需要关心b的大小,还需要关注它的对齐需求。假设您只需要两个字符,并且使用了此代码,那么您的浮点数将在所有当前公共平台上不正确地对齐。

如果您知道编译期间的大小,只需分配一个结构:

代码语言:javascript
复制
struct foo {
    char c[4];
    float f[4];
}

编译器会处理剩下的。否则,如果是动态的,而char数组是6个元素,则需要将该6整到alignof(float)的最接近的倍数(最有可能是8)。当然,您也需要分配足够的内存,即不需要数组元素的和,但也要考虑填充,例如,假设您分配了6个字符,6个浮点数,您可能会得到6个字符,2个填充字节,6*4个字节。

转换本身被认为是合法的,指针算法也是合法的,因为所有这些都指向没有有效类型的分配数组。

另一种不用担心alignof的方法是先放置float数组-- alignof(char)将是1,因此您总是可以尽可能地将它们打包。

票数 5
EN

Stack Overflow用户

发布于 2022-08-07 10:18:08

结构体的编译时标注排除了单个malloc()返回的单个内存块中各种数据类型的运行时量的混合。但是,正在运行的可执行文件可能能够计算所需的存储空间,然后分配和填充足以满足需求的块。

声明类似于以下形式的联合,这是一种数据类型,可用于为内存中正确对齐的子区域分配值。

代码语言:javascript
复制
typedef union {
    char c[8];
    short s[4];
    int i[2];
    float f[2];
    double d;
} t_t;

该联合的单个实例将是8个连续字节,可用于存储1xdouble、2xfloats、2xint.或8个字节。(可能应用程序需要“无符号”类型。)

下面的代码分配(一个)该联合的5个连续实例,然后使用数组和指针语法演示对块的数据写入和检索。它有点像一个“容器”,其不同的内容为代码所知。

代码语言:javascript
复制
void my_main() {
    printf( "sizeof t %d\n", sizeof t_t );

    t_t *x = (t_t *)malloc( 5 * sizeof t_t );

    // x[0] stores an 8byte double
    double *pD = &x[0].d;
    *pD = 365895475.45;

    // x[1] & x[2] store 4x 4byte floats
    float *pF = &x[1].f[0];
    pF[0] = 123.123; pF[1] = 456.456; pF[2] = 789.74; pF[3] = 42.42; 

    // x[3] stores a long string, spilling into x[4]
    char *pC = &x[3].c[0];
    strcpy( pC, "Quick brown fox" );

    printf( "%l.2f %.2f %.2f %.2f %.2f %s.. and '%s'\n",
        *pD, pF[0], pF[1], pF[2], pF[3], pC, &x[4].c );
}

输出:

代码语言:javascript
复制
sizeof t 8
365895475.45 123.12 456.46 789.74 42.42 Quick brown fox.. and 'own fox'

(注意,长字符串从x3溢出到x4。)

这只是个原型..。OP的特殊需求尚不清楚,但这说明了一种技术。

好奇的人可能会考虑使用前8个字节(或16个)来存储以下实例的类型和数量。例如,您可以存储类似于"D7I5C“的内容,以指示'packet‘中有7个双数、5个整数和一个以空结尾的字符串。维度(sizeof of & strlen())和quantities (考虑模块化)将定义所需实例的数量。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73266300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档