Home > Enterprise >  Can we use single malloc() block to represent two different types?
Can we use single malloc() block to represent two different types?

Time:08-08

I am writing a function where I need to call malloc multiple times to allocate memory for very small arrays dynamically (like 4-5 ints). These arrays are used to store different types of datatypes. so I thought of allocating a large memory and use it for all types. Here is what I am trying to.

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


int main() {
    
    char * a = malloc( 4*sizeof(char)   4*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;
}

I am now confused, is this a good allowed practice ?

CodePudding user response:

This is not necessarily a good practice, because you'd need to not only care about the size of b but its alignment requirements. Suppose you only needed 2 chars and you used this code, then your float would be improperly aligned on all currently common platforms.

If you know the sizes during the compilation time, just allocate a structure:

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

and the compiler will take care of the rest. Otherwise, if dynamic, and your char array was say 6 elements, you need to round that 6 up to the nearest multiple of alignof(float) (most likely 8). Of course you need to allocate sufficient amount of memory too, i.e. just not the sum of the array elements but account for the padding as well, i.e. suppose you allocate 6 chars, 6 floats, you'd probably end up with 6 chars, 2 padding bytes, 6 * 4 bytes for floats.

The cast itself is thought to be legal, and so is the pointer arithmetic, since all this is pointing to an allocated array with no effective type.


Another way to not bother with alignof is to put the float array first - alignof(char) will be 1, and therefore you can always pack them as tightly as possible.

CodePudding user response:

Here's a prototype quickly hacked together...

typedef union {
    char c[8];
    short s[4];
    int i[2];
    float f[2];
    double d;
} t_t;

void my_main() {
    printf( "sizeof t %d\n", sizeof t_t );

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

    double *pD = &x[0].d;
    *pD = 365895475.45;

    float *pF = &x[1].f[0];
    pF[0] = 123.123; pF[1] = 456.456; pF[2] = 789.74; pF[3] = 42.42; 

    char *pC = &x[3].c[0];
    strcpy( pC, "Quick brown fox" );

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

Output:

sizeof t 8
365895475.450000 123.123001 456.455994 789.739990 42.419998 Quick brown fox.. and 'own fox'
  • Related