What is the right way to rethink memory in C?

I have long lost track of the number of times I did something like this in C:

struct foo f; struct foo* pf = &f; char* pc = (char*) pf; transmit(pc, sizeof(f)); 

Or perhaps:

 char* buffer[1024]; receive(buffer, 1024); float values[256]; for(int ii = 0; ii < 256; ii++) { float* pf = (float*)(buffer + ii*4); values[ii] = *pf; } 

Or maybe:

 uint32_t ipAddress = ...; uint8_t* p = (uint8_t*)&ipAddress; uint8_t octets[4] = {p[0], p[1], p[2], p[3]}; printf("%d.%d.%d.%d\n", octets[0], octets[1], octets[2], octets[3]); 

I just found that reinterpreting a piece of memory like this by translating to a different type of pointer causes undefined behavior. And yet, all the above examples should be absolutely necessary. What is the correct way to do them?

+4
source share
1 answer

Listing char * (or unsigned char * or typedefs) is a special case and does not cause undefined behavior.

From Specification C, 6.3.2.3 Indices , clause 7:

When a pointer to an object is converted to a pointer to a character type, the result points to the low address byte of the object. Successive increments of the result, up to the size of the object, give pointers to the remaining bytes of the object.

Your first and third examples are covered by this case. The second example is a bit strange, but will probably work on most systems. What you really have to do is either directly read in values :

 float values[256]; receive(values, sizeof values); // assuming receive() takes a "void *" parameter 

Or something like this (to avoid alignment problems):

 char buffer[1024]; receive(buffer, sizeof buffer); float values[256]; for(int i = 0; i < 256; i++) { char *pf = (char *)&values[i]; memcpy(pf, buffer + i * sizeof(float), sizeof(float)); } 

(Note: I changed buffer as a char array - I assume it was a typo in your question).

+5
source

Source: https://habr.com/ru/post/1488548/


All Articles