在C中将整数复制到char缓冲区

时间:2015-08-03 14:39:57

标签: c

  uint32_t after = 0xe1ca95ee;
  char new_buf[4];
  memcpy(new_buf, &after, 4);
  printf("%x\n", *new_buf); // I want to print the content of new_buf

我想将after的内容复制到new_buf。但结果令人困惑。 printf给了我ffffffee。它看起来像一个地址。我已经取消引用new_buf

根据评论,我无法使用memcpystrncpy来执行此任务。但为什么? memcpystrncpy仅用于处理char *?但after的内容在记忆中。

PS:我知道我应该使用sprintfsnprintf。如果你可以解释为什么memcpystrncpy不适合这种情况,我很感激。

3 个答案:

答案 0 :(得分:5)

这就是问题所在:

printf("%x\n", *new_buf);

这为您提供了所要求的内容:它使用%x格式在 new_buf 位置打印 char 。该位置已经包含0xee(在您成功的memcpy之后,首先是最不重要的字节,因为您最有可能在Intel机器上,小端),但它打印为0xffffffee(负数),因为它是 char 而不是 unsigned char ,因为当然0xee是有符号字节(> 0x7F,最高位设置)

您应该使用:

printf("%x\n", *((unsigned int*)new_buf));

...编辑如下......

或者更确切地说:

printf("%x\n", *((uint32_t*)new_buf));

答案 1 :(得分:3)

如果你这样做:

int i;
for (i = 0; i < 4; i++) printf("%x\n", new_buf[i]);

你可以看到它打印

ffffffee
ffffff95
ffffffca
ffffffe1

所以你的字节都在那里。正如@GeorgeAndré所指出的,它们是有符号字节,所以你看到f被填充到前面,因为数字是负的,它总是打印4个字节,ee用32位表示{ {1}}。您可能在一个小端机器上,因此最低有效字节ffffffee实际上存储在最低内存位置,这就是为什么在解除引用ee时得到数字的“最后”字节的原因。另一部分已被其他人回答,您必须在打印期间将new_buf声明为未签名或投票。

new_buf

或者

   uint32_t after = 0xe1ca95ee;
   char new_buf[4];
   memcpy(new_buf, &after, 4);
   printf("%x\n", *((unsigned char*)new_buf));

答案 2 :(得分:0)

如果您尝试复制整数并将其作为整数打印到stdout,则基数为16:

char new_buf[4];
...
printf("%x\n", *new_buf);

无论您存储在new_buf中的是什么,它的类型仍然是char[4]。因此,*new_buf类型char(它与new_buf[0]完全相同)。

因此,您获取整数的第一个 char (可能是高字节或低字节,具体取决于平台),将其自动提升为整数,然后打印作为基数为16的无符号整数。

memcpy确实已将您的值复制到数组中,但如果要打印它,请使用

printf("%x\n", *(uint32_t *)new_buf);

printf("%02x%02x%02x%02x\n", new_buf[0], new_buf[1], new_buf[2], new_buf[3]);

(但请注意,在后一种情况下,您的字节顺序可能会颠倒,具体取决于平台)。

如果您正在尝试创建一个包含您的号码的base-16字符串表示形式的char数组:

不要使用memcpy,它不会从整数转换为字符串表示。

尝试

uint32_t after = 0xe1ca95ee;
char new_buf[1 + 2*sizeof(after)];
snprintf(new_buf, sizeof(new_buf), "%x", after);
printf("original %x formatted as '%s'\n", after, new_buf);

(缓冲区的大小为每个八位字节提供2个字符,加上一个用于nul-terminator)。