3

char次のようなマイクロコントローラ デバイスからタイプのバッファを読み取っています。

char data_buffer[DATA_LEN];
FILE *aq_dev = fopen(argv[1], "r");

fread(data_buffer, 1, DATA_LEN, aq_dev);

fclose(aq_dev);

このバッファ ブロブには、符号なしの 16 ビット整数があり、それぞれがバッファ内の 2 つのエントリに分散されています。たとえば、

data_buffer[10] = 0x07
data_buffer[11] = 0xc3

これは 1987 に等しいものとして読みたいと思います。最初はポインターを0x07c3使用してバッファーにアクセスし、値を直接読み取ることができると思っていたにもかかわらず、uint16_t奇妙なビットマスキングを行う必要があります。

int value = (buffer[10] << 8) + buffer[11];

35000 を超える間違った値を与えますが、一見役に立たないビットマスキングのような

int value = ((buffer[10] & 0xff) << 8) + (buffer[11] & 0xff);

正しい値を返します。

charの配列のエントリが1 バイトよりも大きくなるにはどうすればよいですか? limits.h(Linux、x86_64)によると、 #define CHAR_BIT 8.

誰かが私のコードの何が問題なのか教えてもらえますか? 前もって感謝します!

4

1 に答える 1

6

あなたの問題はchar、プラットフォームで署名されていることです。したがって、 の上位ビットbuffer[11]が設定されている場合、それは負の値になり、式でそれを使用すると、最初に (負の) 整数に昇格され、 のchar上位ビットがすべての上位ビット位置に効果的に伝播されます。

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended

&-ing が0xff機能する理由は、操作が実行される前にchar値が昇格されるためです。int&

buffer[11]   (char)                0xc3 -61
             (int)           0xffffffc3 -61      // sign-extended
    & 0xff   (int)           0x000000c3 195

unsigned char修正は、ビット操作を実行する前にキャストすることです。

int value = (((unsigned char) buffer[10]) << 8) | ((unsigned char) buffer[11]);

buffer[11]   (char)                0xc3 -61
             (unsigned char)       0xc3 195
             (int)           0x000000c3 195

bufferの配列を作成する方がおそらく簡単ですunsigned char

于 2012-10-11T17:29:31.877 に答える