【问题标题】:How do I convert a 64bit integer to a char array and back?如何将 64 位整数转换为 char 数组并返回?
【发布时间】:2012-03-14 03:58:18
【问题描述】:

我在将 int64_t 转换为 char 数组并返回时遇到问题。我不知道下面的代码有什么问题,这对我来说完全合乎逻辑。如图所示,该代码适用于a,但不适用于第二个数字b,它显然属于int64_t 的范围。

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

void int64ToChar(char mesg[], int64_t num) {
  for(int i = 0; i < 8; i++) mesg[i] = num >> (8-1-i)*8;
}

int64_t charTo64bitNum(char a[]) {
  int64_t n = 0;
  n = ((a[0] << 56) & 0xFF00000000000000U)
    | ((a[1] << 48) & 0x00FF000000000000U)
    | ((a[2] << 40) & 0x0000FF0000000000U)
    | ((a[3] << 32) & 0x000000FF00000000U)
    | ((a[4] << 24) & 0x00000000FF000000U)
    | ((a[5] << 16) & 0x0000000000FF0000U)
    | ((a[6] <<  8) & 0x000000000000FF00U)
    | ( a[7]        & 0x00000000000000FFU);
  return n;
}

int main(int argc, char *argv[]) {
  int64_t a = 123456789;
  char *aStr = new char[8];
  int64ToChar(aStr, a);
  int64_t aNum = charTo64bitNum(aStr);
  printf("aNum = %lld\n",aNum);

  int64_t b = 51544720029426255;
  char *bStr = new char[8];
  int64ToChar(bStr, b);
  int64_t bNum = charTo64bitNum(bStr);
  printf("bNum = %lld\n",bNum);
  return 0;
}

输出是

aNum = 123456789
bNum = 71777215744221775

代码还给出了两个我不知道如何摆脱的警告。

warning: integer constant is too large for ‘unsigned long’ type
warning: left shift count >= width of type

【问题讨论】:

  • 第二个警告是关键。 &lt;&lt; 的操作数提升为int,所以a[0]&lt;&lt;56 将始终为0。尝试((int64_t)a[0]) 等。第一个警告是关于51544720029426255,你需要说51544720029426255LL。

标签: c linux


【解决方案1】:

这很简单,问题是您在 char 数组中移动位,但 a[i] 的大小是 4 个字节(向上转换为 int),所以您的移位刚刚超出范围。尝试在您的代码中替换它:

int64_t charTo64bitNum(char a[]) {
  int64_t n = 0;
  n = (((int64_t)a[0] << 56) & 0xFF00000000000000U)
    | (((int64_t)a[1] << 48) & 0x00FF000000000000U)
    | (((int64_t)a[2] << 40) & 0x0000FF0000000000U)
    | (((int64_t)a[3] << 32) & 0x000000FF00000000U)
    | ((a[4] << 24) & 0x00000000FF000000U)
    | ((a[5] << 16) & 0x0000000000FF0000U)
    | ((a[6] <<  8) & 0x000000000000FF00U)
    | (a[7]        & 0x00000000000000FFU);
  return n;
}

通过这种方式,您将在进行移位之前将char 转换为 64 位数字,并且您不会超出范围。你会得到正确的结果:

entity:Dev jack$ ./a.out 
aNum = 123456789
bNum = 51544720029426255

只是一个旁注,我认为这也可以正常工作,假设您不需要查看 char 数组内部:

#include <string.h>

void int64ToChar(char a[], int64_t n) {
  memcpy(a, &n, 8);
}

int64_t charTo64bitNum(char a[]) {
  int64_t n = 0;
  memcpy(&n, a, 8);
  return n;
}

【讨论】:

  • 我更喜欢你的替代方案,memcpy 到 int64_t 变量,但我认为它不会起作用,例如:char szInput = "51544720029426255"; / 17 字节,超过 8 字节 */ memcpy( &n, szInput, 8);会导致溢出,你不觉得吗?谢谢
  • 否,因为您指定在任何情况下都将通过第三个参数复制 8 个字节。
  • 哦耶..但它只会复制前8个字节,cout
  • 值将完全不同,您将 8 个 ASCII 字符存储为 64 位值,但内部数值将根据 8 个字符转换为整数表示的内部表示形式打印,因此没有直接转换。要将字符串文字转换为 u64(不仅仅是将其存储在 u64 中),您应该使用适当的函数 atoul
【解决方案2】:
void int64ToChar(char mesg[], int64_t num) {
    *(int64_t *)mesg = num; //or *(int64_t *)mesg = htonl(num);

}

【讨论】:

    【解决方案3】:

    您使用的是 32 位机器吗? IIRC 我认为 U 后缀仅表示“unsigned int”或“unsigned long”,它们在 32 位机器上都是 32 位。我认为您希望在位移中使用“无符号长长”(64 位)文字,或 0xFF00000000000000ULL

    http://en.kioskea.net/faq/978-c-language-handling-64-bit-integers#unsigned-64-bit-integer

    【讨论】:

      【解决方案4】:

      charTo64bitNum 中,您需要在转换之前将字符转换为 64 位:

      (((int64_t)a[0] << 56) & 0xFF00000000000000U)
      

      【讨论】:

        猜你喜欢
        • 2015-09-19
        • 1970-01-01
        • 2012-01-11
        • 1970-01-01
        • 2023-03-28
        • 2016-04-30
        • 1970-01-01
        • 2015-10-08
        • 2019-08-17
        相关资源
        最近更新 更多