1

我有一个像这样的字符缓冲区

char *buff = "aaaa0006france";

我想提取字节 4 到 7 并将其存储在一个 int 中。

int i;
memcpy(&i, buff+4, 4);
printf("%d ", i);

但它会打印垃圾值。

这有什么问题?

4

3 回答 3

5

字符串

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将文本字符串转换为数字的函数将文本显式转换为整数。

希望这可以帮助!

于 2013-01-23T05:38:31.403 回答
2

这里需要注意两点

  • 字符是如何存储的
  • 系统的字节序

每个字符(字母、数字或特殊字符)都存储为 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 中存在的任何ab。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

于 2013-01-23T11:11:38.937 回答
1

下面的代码可能会帮助你...

#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;
}
于 2013-01-23T05:52:17.647 回答