[英]How to make int from char[4]? (in C)
我有char [4]并且在其中: a[0] = 0x76
a[1] = 0x58
a[2] = 0x02
a[3] = 0x00
我想打印它为int
,你能告诉我怎么做那?
这可行,但根据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);
我认为工会是这样做的合适方式。
#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);
}
其他选项可以使用按位运算符|
和<<
左移,如下(了解阅读评论):
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] << ( 0 * 8);
可以只是i = i | a[3];
i = i | a[3];
,我这样写,以保持代码统一。
编辑:
哦,你可以这样做:
i = 0 |
a[0] << ( 3 * 8) |
a[1] << ( 2 * 8) |
a[2] << ( 1 * 8) |
a[3] << ( 0 * 8);
看看这里: Codepade的工作代码。
值是以big-endian还是little-endian顺序存储在数组中的? 可移植的方法是基于移位和掩码,注意在一般情况下,将设置一些高位,并且您的普通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)
。 如果您知道plain char
是无符号的,则可以删除掩码操作。 你也可以使用强制转换: unsigned char *u = (unsigned char *)a;
然后取消引用u
而不是a
。
如果你想把它读成大端或小端整数,只需做一些位移:
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);
如果要将其作为native-endian整数读取,可以将数组转换为指向整数的指针并取消引用。 请注意,前者只允许char
数组-这是任何其他类型的,这样做打破了C'S严格别名规则,所以这不会是安全的或便携式的。 例如:
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;
或者,您可以直接使用union,或者只使用memcpy()
数据。 这两个都是安全和可移植的,只要char
是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
为4个字节。 uint32_t
类型在头文件<stdint.h>
定义,如果它由编译器定义,则保证为32位宽。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.