4

很久以前,我已经记不清我在 C 中做过多少次这样的事情了:

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

也许:

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;
}

或者可能:

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]);

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

4

1 回答 1

5

强制转换为char *(或其unsigned char *类型定义)是一种特殊情况,不会导致未定义的行为。

来自 C 规范,6.3.2.3 Pointers,第 7 段:

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

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

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

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

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));
}

(请注意,我改为buffer数组char- 我认为这是您问题中的错字)。

于 2013-06-27T16:51:33.590 回答