treating allocated memory as a different type

Suppose I allocate some memory.

char* buffer = (char*)my_malloc(2062);

I assign char values to the first 14 bytes from a previously defined array named header.

memcpy(buffer, header, 14);

Then I want to treat the rest of the allocated space as pointers to float.

float* float_buffer = (float*)(buffer + 14);
some_function(float_buffer);

Then at some point later on I need to send all the data out.

transmit(buffer);
my_free(buffer);

Is this correct way to treat memory? Is the float* cast ok? I am having issues where I am losing values and not getting the correct results. My question is: If you have to treat allocated memory as different types but then send it as char* at the end of the processing.....is this the correct way to do it?

I checked the ptr values and they are the same when they are float* and char* but I am not getting the correct result.

One of my restrictions is that I can only initially allocate one block of memory from a static buffer. So calling another malloc as a different type (float*) is not allowed.


To make this work (portably, at least), you would have to ensure (at a minimum) that the float_buffer was sizeof(float)-aligned. You could do this by allocating sizeof(float) - 1 extra bytes, observing the result of the malloc call modulo sizeof(float), and ignoring the first few bytes as appropriate. (You would, of course, have to keep the original pointer around in order to make the free() call.)

You probably don't want to do this, though. It sounds like the purpose of the 'buffer' is to accumulate data to be sent over a network or something like that, and that the floats are going to be copied in from somewhere else. What you should really do is cast the other way around: treat the buffer as a char[] always, and reinterpret the source floats as a sequence of chars when you copy them over. That is

char* buffer = malloc(total_size);
char* float_start = buffer + header_size;
memcpy(float_start, (char*)float_source, sizeof(float) * float_count);
transmit(buffer, total_size);
free(buffer);

Conceptually, this is OK - but you have to do some additional work to ensure it will work reliably.

A potential problem is that you cannot just access any arbitrary address as a float . There may be specific alignment requirements - the address returned by malloc() is required to be correctly aligned for access as any type, but once you add 14 to that address, all bets are off (except for char ).

To ensure the correct alignment, you must ensure that the address you add to buffer is a multiple of sizeof(float) . You can do that by adding padding using the following formula:

#define PAD_OFFSET(offset, type) ((offset) + sizeof(type) - 1) & ~(sizeof(type) - 1))

float *float_buffer = (float *)(buffer + PAD_OFFSET(14, float));

Note that this will create a gap - padding - between your chars and your floats.

Alternatively, you can define a struct , and the compiler will figure the padding out for you. This uses a C99 feature called a flexible array member:

struct foo {
    char abc[14];
    float xyz[];
};

struct foo *buffer = malloc(2062);
memcpy(&buffer->abc, header, 14);
some_function(&buffer->xyz);
transmit(buffer); /* Presuming transmit() expects a void * parameter. */

If you wish to do it without padding, you cannot directly access the memory in buffer as floats - you will have to create a temporary array and copy it in:

float temp[500]; /* Or whatever size */
some_function(&temp);
memcpy(buffer + 14, temp, sizeof temp);

I am speculating here, but since the prototype for malloc is

void *malloc(size_t size);

you are essentially casting the buffer of type void* to char*, so later casting another chunk of the buffer to float* would be fine, so long as you take care of the pointer accounting properly.

链接地址: http://www.djcxy.com/p/80206.html

上一篇: 通过Malloc增加分配给结构的内存大小

下一篇: 将分配的内存视为不同的类型