4

我试图在所有小端系统中以可移植的方式将字节从 int 转换为一系列字符。

我有以下代码:

#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, b,进入时c,他们将被提升为。它们是符号扩展的。这就是为什么你会得到所有这些领先的 ​​s。dprintf()intff

GDB 正在报告正确的值,因为它正在chars直接读取。(因此没有整数提升)

于 2012-07-19T00:36:38.070 回答
1

在比较过程中abcd被提升为int。由于它们都是char,因此最高有效位被视为符号位。int将 MSB 填充到更高位的提升。

0x12的 MSB 为 0, 和0xef0xcdMSB0xab为 1。这就是为什么升级后你会得到0x00000012but0xffffffef和。0xffffffcd0xffffffab

如果你改变

char a, b, c, d;

进入

unsigned char a, b, c, d;

然后你可以得到你所期望的。

于 2012-07-19T00:39:24.223 回答