我有一个像这样的字符缓冲区
char *buff = "aaaa0006france";
我想提取字节 4 到 7 并将其存储在一个 int 中。
int i;
memcpy(&i, buff+4, 4);
printf("%d ", i);
但它会打印垃圾值。
这有什么问题?
字符串
0006
没有与整数 6 相同的二进制表示。相反,它的位表示为四个 ASCII 字符,分别表示字形 0、字形 0、字形 0、然后是字形 6。这具有十六进制表示
0x30303036
如果您尝试在 little-endian 系统上盲目地将这些位重新解释为数字,您会得到 808,464,438。在大端系统上,你会得到 909,127,728。
如果要将字符串的子字符串转换为数字,则需要寻找将文本字符串转换为数字的函数。您可能想尝试这样的事情:
char digits[5];
/* Copy over the digits in question. */
memcpy(digits, buff + 4, 4);
digits[4] = '\0'; /* Make sure it's null-terminated! */
/* Convert the string to a number. */
int i = strtol(digits + 4, NULL, 10);
这使用strtol
将文本字符串转换为数字的函数将文本显式转换为整数。
希望这可以帮助!
这里需要注意两点
每个字符(字母、数字或特殊字符)都存储为 7 位 ASCII 值。在memcpy
将字符串(字符数组)“0006”转换为 4 字节的 int 变量时,我们必须将字符串的地址作为源,将 int 的地址作为目标,如下所示。
char a[] = "0006";
int b = 0, c = 6;
memcpy(&b, a, 4);
a 和 b 的值存储如下。
a 00110110 00110000 00110000 00110000
b 00000000 00000000 00000000 00000000
c 00000000 00000000 00000000 00000110
MSB LSB
因为字符的 ASCII 值0
是 48,6
字符是 54。现在memcpy
将尝试复制 to 中存在的任何a
值b
。bmemcpy
的值如下所示
a 00110110 00110000 00110000 00110000
b 00110110 00110000 00110000 00110000
c 00000000 00000000 00000000 00000110
MSB LSB
接下来是字节序。现在考虑我们0006
以其他方式将值保存到字符缓冲区,a[0] = 0; a[1] = 0; a[2]=0; a[3] = 6;
如果我们这样做,如果它是小端机器memcpy
,我们将获得 100663296() 而不是 6 的值。0x6000000
在大端机器中,您将6
仅获得该值。
c 00000110 00000000 00000000 00000000
b 00000110 00000000 00000000 00000000
c 00000000 00000000 00000000 00000110
MSB LSB
所以这两个问题我们在编写一个将数字宪章转换为整数值的函数时需要考虑。这些问题的简单解决方案是利用现有的系统api atoi
。
下面的代码可能会帮助你...
#include <stdio.h>
int main()
{
char *buff = "aaaa0006france";
char digits[5];
memcpy(digits, buff + 4, 4);
digits[4] = '\0';
int a = atoi(digits);
printf("int : %d", a);
return 0;
}