4

すべてのリトル エンディアン システムで移植可能な方法で、バイトを int から一連の char に取得しようとしています。

次のコードがあります。

#include <stdio.h>

int
main()
{
  int i = 0xabcdef12;
  printf("i: %x\n", i);
  char a, b, c, d;
  a = (i >> 000) & 0xFF;
  b = (i >> 010) & 0xFF;
  c = (i >> 020) & 0xFF;
  d = (i >> 030) & 0xFF;
  printf("a b c d: %x %x %x %x\n", a , b, c, d);
  if(a == 0x12)
    printf("a is 0x12\n");
  if(b == 0xef)
    printf("b is 0xef\n");
  if(c == 0xcd)
    printf("c is 0xcd\n");
  if(d == 0xab)
    printf("d is 0xab\n");
  if(a == 0xffffff12)
    printf("a is 0x12\n");
  if(b == 0xffffffef)
    printf("b is 0xffffffef\n");
  if(c == 0xffffffcd)
    printf("c is 0xffffffcd\n");
  if(d == 0xffffffab)
    printf("d is 0xffffffab\n");
  return 0;
}

-Wall を使用すると、このコードは警告なしでコンパイルされます。

実行すると、次のようになります。

i: abcdef12
a b c d: 12 ffffffef ffffffcd ffffffab
a is 0x12
b is 0xffffffef
c is 0xffffffcd
d is 0xffffffab

ここにいくつかの gcc プリントがあります:

Breakpoint 1, main () at test.c:14
14    if(a == 0x12)
(gdb) p/x a
$1 = 0x12
(gdb) p/x b
$2 = 0xef
(gdb) p/x c
$3 = 0xcd
(gdb) p/x d
$4 = 0xab

私は何か間違ったことをしていると確信しています。次の質問のいくつかに答えていただければ、何が起こっているのかを理解するのに本当に役立ちます。

  • char が 0xff より大きい値を持つにはどうすればよいですか?
  • & 0xffビットマスクが機能していないのは何ですか?
  • gdb が正しい値を報告するのはなぜですか?

そして、誰かが int から char[] への信頼できる (システムに依存しないが、エンディアンは重要ではない) 方法を持っているなら、それは素晴らしいことです。

4

2 に答える 2

5

これが簡単な修正です。

変化する:

char a, b, c, d;

unsigned char a, b, c, d;

その理由はchar、システムに署名されているためです。, ,をに渡すとa、に昇格します。それらは符号拡張されています。そのため、これらすべての主要なs を取得します。bcdprintf()intff

GDB はchars直接読み取っているため、正しい値を報告しています。(したがって、整数の昇格はありません)

于 2012-07-19T00:36:38.070 に答える
1

比較中、abcおよびdは としてプロモートされintます。すべてcharであるため、最上位ビットは符号ビットとして扱われます。intMSB を上位ビットに埋めるための昇格。

0x12の MSB は 0、および0xef0xcdおよび0xabの MSB は 1 です。そのため、プロモーション後に0x00000012but 0xffffffef0xffffffcdおよびが得られます0xffffffab

変えたら

char a, b, c, d;

の中へ

unsigned char a, b, c, d;

その後、期待どおりの結果を得ることができます。

于 2012-07-19T00:39:24.223 に答える