在C中重新解释内存的正确方法是什么?

Tom*_*Tom 4 c memory pointers undefined-behavior

很久以前,我在C中做过类似事情的次数已经丢失了:

struct foo f;
struct foo* pf = &f;
char* pc = (char*) pf;
transmit(pc, sizeof(f));
Run Code Online (Sandbox Code Playgroud)

也许:

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;
}
Run Code Online (Sandbox Code Playgroud)

或者可能:

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]);
Run Code Online (Sandbox Code Playgroud)

我刚刚发现通过转换为另一种指针类型来重新解释这样的内存会调用未定义的行为.然而,所有上述例子都是绝对必要的.这样做的正确方法是什么?

Car*_*rum 5

转换为char *(或unsigned char *或者为typedef)是一种特殊情况,不会导致未定义的行为.

从C规范,6.3.2.3指针,第7段:

当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节.结果的连续增量(直到对象的大小)产生指向对象的剩余字节的指针.

本案涵盖了您的第一个和第三个示例.第二个例子有点狡猾,但可能适用于大多数系统.你真正应该做的是直接阅读values:

float values[256];
receive(values, sizeof values); // assuming receive() takes a "void *" parameter
Run Code Online (Sandbox Code Playgroud)

或类似的东西(以避免对齐问题):

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));
}
Run Code Online (Sandbox Code Playgroud)

(注意我改成buffer了一个char数组 - 我认为这是你问题中的拼写错误).

  • 当然:[C11(PDF链接)](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)或[C99(PDF链接)](http:// www .open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf),你的选择. (2认同)