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 *その typedef)へのキャストは特殊なケースであり、未定義の動作は発生しません。

C仕様、6.3.2.3 Pointers、段落7から:

オブジェクトへのポインターが文字型へのポインターに変換されると、結果はオブジェクトの最下位アドレスのバイトを指します。オブジェクトのサイズまで結果を連続的にインクリメントすると、オブジェクトの残りのバイトへのポインタが生成されます。

最初と3番目の例は、このケースでカバーされています。2 番目の例は少し厄介ですが、おそらくほとんどのシステムで動作します。あなたが本当にすべきことは、次のいずれかを直接読み取ること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 に答える