首页 > 解决方案 > 将 long long 存储在 char 数组中而不截断

问题描述

所以我有一个类型的元素数组uint8_t存储在一个数组中,并且需要基本上将它们连接起来,并生成结果的字符串形式。有没有办法long long在不截断的情况下存储在 char 数组中?换句话说,如何在 char 数组中存储 64 位?在下面的例子中abacce"abacce"

void concat(uint8_t *arr, int size) {
   unsigned long long val=0;
   for (int i=0; i<size; i++) {
      val <<= 8;
      val |= arr[i];
   }
   printf ("%x\n", val);  // abacce -- perfect!
   
   // now I need to convert this to a char array since I need to pass this to a function that takes in a char array!!  -- below is my failed attempt...

   char arr[10];
   sprintf(arr, "%x", val); // char = 8 bytes so it truncates the first byte only!
}

int main(void) {
   uint8_t arr[] = {0xab, 0xac, 0xce};
   concat(arr, sizeof(arr)/sizeof(arr[0]);
}

好的,有人在评论中提到%llx将存储 long long unsigned 的十六进制表示并在在线 IDE 中,它似乎可以工作,但是当我在 eclipse 中尝试以下操作时,我得到lx

void concat(uint8_t *arr, int size, char *str) {
       unsigned long long val=0;
       for (int i=0; i<size; i++) {
          val <<= 8;
          val |= arr[i];
       }
      sprintf(str, "%llx", var); // str has "lx" instead of "0x30abcdababcd"
      return val;
}
int main(void) {
   char str[20] = {0};
   uint8_t arr[] = {0x30, 0xab, 0xcd, 0xab, 0xab, 0xcd};
   long long unsigned var = concat(arr, sizeof(arr)/sizeof(arr[0], str);
}

标签: carraysstring

解决方案


您有几个问题应该从 IDE 中跳出来:

  sprintf(str, "%llx", var);

var没有贴花。你的意思是val

接下来,由于不匹配,您有一个不完整的表达式'('

    sizeof(arr)/sizeof(arr[0], str);

不如sizeof arr/ sizeof arr[0].

接下来,您尝试void在上述问题的行中分配类型函数的返回:

long long unsigned var = concat(arr, sizeof(arr)/sizeof(arr[0], str);

您的声明concat()是:

void concat(...

您不能long long unsignedvoid. 你想要的是:

unsigned long long concat(uint8_t *arr, int size, char *str)
{
    unsigned long long val=0;
    for (int i=0; i<size; i++) {
        val <<= 8;
        val |= arr[i];
    }
    sprintf(str, "%llx", val); // str has "lx" instead of "0x30abcdababcd"
    return val;
}

现在您的代码运行良好。printf在末尾添加 amain()以验证 and 的值varstr例如

int main(void) {
    char str[20] = {0};
    uint8_t arr[] = {0x30, 0xab, 0xcd, 0xab, 0xab, 0xcd};
    long long unsigned var = concat(arr, sizeof arr /sizeof arr[0], str);
    printf ("%llx   %s\n", var, str);
}

示例使用/输出

$ ./bin/concatuint8
30abcdababcd   30abcdababcd

您的编译器应该为您提供上述每个错误发生的行。如果不是,那么您正在使用的 IDE 或您的配置方式有问题。在 Linux 或 Windows 中简单地从命令行编译只需不到一秒钟,并且会显示所有启用警告的问题(例如-Wall -Wextra -pedantic -Wshadow,对于 gcc/clang 或/W3对于 VS)

看看事情,让我知道如果你有更多的问题。

编辑 2 关于 STM32 F401 微控制器

经过进一步讨论,您正在使用STM32 F401微控制器。在这些或任何微控制器上,您在没有操作系统的“裸机”上编译和运行代码,您正在所谓的独立环境 C11 标准 - 5.1.2.1 独立环境中工作。您使用gcc-eabi而不是gcc-none-eabi表明您的目标是微控制器上的某种操作系统。它也可能影响可用的东西。

问题在于,您必须使用的大部分内容都是实现定义的,不一定符合 C 标准。对于具有可以编译和链接的几种不同模式(目标)的手臂板尤其如此。在这里,您有一个thumb模式和arm模式,它们会影响使用的寄存器大小以及可用的整数大小。虽然 Cortex-M4 进程将支持ll,ullllulength 修饰符,但它们可能不适用于所有编译器和链接器模式ARM Compiler Toolchain - long long

您将需要仔细检查您的编译器选项和 IDE 选项,以确保您的目标是支持long long64 位的构建并使llor ullorllu修饰符可用。这将来自您正在使用的操作系统Free RTOS?和编译器文档。gcc ARM 选项解决了编译器选项,但是无论您是在“裸机”上工作还是针对在您的板上运行的某种类型的操作系统,也会有所不同。

这是使用微控制器和嵌入式系统的挑战。除了学习 C 语言之外,您对特定硬件本身也有相同的学习曲线。您需要将您的手臂放在操作系统(如果有的话)与 Cortex-M4 处理器选项一起定位。我建议确定您正在使用的确切操作系统(如果有的话),然后重新提出一个单独的严格定制的问题,类似于“为什么%llx修改器printf不能在具有 Cortex M4 处理器的 STM32 F401EE 板上工作”。使用 ARM 标签并查找任何特定于 STM32 板的标签。这将使问题定义在一个水平上,从而邀请具有该特定知识的人来回答。


推荐阅读