4

我有 char a[4] 并在其中: a[0] = 0x76 a[1] = 0x58 a[2] = 0x02 a[3] = 0x00 我想将其打印为int,你能告诉我该怎么做吗?

4

5 回答 5

11

这可行,但会根据 int、endian 等的大小给出不同的结果。

#include <stdio.h>

int main(int argc, char *argv[])
{

    char a[4];
    a[0] = 0x76;
    a[1] = 0x58;
    a[2] = 0x02;
    a[3] = 0x00;
    printf("%d\n", *((int*)a));
    return 0;
}

这更干净,但您仍然有字节序/大小问题。

#include <stdio.h>

typedef union {
    char c[4];
    int i;
} raw_int;

int main(int argc, char *argv[])
{

    raw_int i;
    i.c[0] = 0x76;
    i.c[1] = 0x58;
    i.c[2] = 0x02;
    i.c[3] = 0x00;
    printf("%d\n", i.i);
    return 0;
}

要强制一定的字节顺序,请int手动构建:

int i = (0x00 << 24) | (0x02 <<< 16) | (0x58 << 8) | (0x76);
printf("%d\n", i);
于 2013-07-11T20:07:25.023 回答
6

我认为工会是做到这一点的适当方式。

#include <stdio.h>
#include <stdint.h>

union char_int {
    char chars[4];
    int32_t num;
};

int main() {
    union char_int tmp;

    tmp.chars[0] = 0x76;
    tmp.chars[1] = 0x58;
    tmp.chars[2] = 0x02;
    tmp.chars[3] = 0x00;
    printf("%d\n", tmp.num);
}
于 2013-07-11T20:03:15.867 回答
1

存储在数组中的值是大端还是小端?可移植的方法是基于移位和掩码,注意在一般情况下,将设置一些高位,并且您的普通char类型可能是有符号或无符号的。

小端序

int i = (a[3] << 24) | ((a[2] & 0xFF) << 16) | ((a[1] & 0xFF) << 8) | (a[0] & 0xFF);

大端序

int i = (a[0] << 24) | ((a[1] & 0xFF) << 16) | ((a[2] & 0xFF) << 8) | (a[3] & 0xFF);

您可以更改它们,以便每个术语始终采用((a[n] & 0xFF) << m). 如果您知道 plainchar是无符号的,则可以删除掩码操作。您还可以使用强制转换:unsigned char *u = (unsigned char *)a;然后取消引用u而不是a.

于 2013-07-11T20:12:59.870 回答
1

其他选项可以使用按位运算符|<<左移,如下(理解阅读注释):

int main(int argc, char *argv[])
{

  char a[4];
  int32_t  i = 0;  // 32 bits = 4 bytes
  a[0] = 0x76;
  a[1] = 0x58;
  a[2] = 0x02;
  a[3] = 0x00;

  i = 0;   // initial  value must be `0`
  i = i | a[0] << ( 3 * 8); // 0x76 => 0x76 00 00 00, gives i = 0x76 00 00 00  
  i = i | a[1] << ( 2 * 8); // 0x58 => 0x00 58 00 00, gives i = 0x76 58 00 00
  i = i | a[2] << ( 1 * 8); // 0x02 => 0x00 00 02 00, gives i = 0x76 58 02 00
  i = i | a[3] << ( 0 * 8); // 0x02 => 0x02   
                            //      => 0x00 00 00 02, gives i = 0x76 58 02 00 

  printf("Hex: %x\nDec: %d \n", i, i);
  return 0;
}

输出:

$ gcc  -Wall -pedantic yy.c 
$ ./a.out 
Hex: 76580200            <- "hex decimal"
Dec: 1985479168          <- "decimal"

注意:i = i | a[3] << ( 0 * 8);可以只是i = i | a[3];,我这样写是为了保持代码统一。

编辑:

哦,你可以这样做:

i = 0 | 
     a[0] << ( 3 * 8) | 
     a[1] << ( 2 * 8) |
     a[2] << ( 1 * 8) |
     a[3] << ( 0 * 8);

看这里:用于工作代码的Codepade 。

于 2013-07-11T20:11:20.510 回答
1

如果您想将其读取为大端或小端整数,只需进行一些位移:

char a[4] = {0x76, 0x58, 0x02, 0x00};

// Big-endian:
uint32_t x = ((uint8_t)a[0] << 24) | ((uint8_t)a[1] << 16) | ((uint8_t)a[2] << 8) | (uint8_t)a[3];

// Little-endian:
uint32_t y = (uint8_t)a[0] | ((uint8_t)a[1] << 8) | ((uint8_t)a[2] << 16) | ((uint8_t)a[3] << 24);

如果您想将其作为本机字节序整数读取,您可以将数组转换为指向整数的指针并取消引用它。请注意,前者仅允许用于数组char——对于任何其他类型,这样做会破坏 C 的严格别名规则,因此不安全或不便携。例如:

char a[4] = {0x76, 0x58, 0x02, 0x00};

// Cast to pointer to integer and dereference.  This is only allowed if `a' is an
// array of `char'.
uint32_t x = *(uint32_t *)a;

或者,您可以使用联合,或者memcpy()直接使用数据。这两个都是安全且可移植的,只要 achar是 8 位(它的位大小由宏给出CHAR_BIT)。

char a[4] = {0x76, 0x58, 0x02, 0x00};
uint32_t x;

// Copy the data directly into x
memcpy(&x, a, sizeof(x));

// Use a union to perform the cast
union
{
    char a[4];
    uint32_t x;
} u;
memcpy(u.a, a, sizeof(a));
// u.x now contains the integer value

请注意,我uint32_t在上面的所有示例中都使用过,因为int不能保证在所有系统上 an 都是 4 字节。类型uint32_t在头文件中定义<stdint.h>,如果它是由您的编译器定义的,则保证为 32 位宽。

于 2013-07-11T20:17:04.030 回答