【问题标题】:uint64_t to an array - C languageuint64_t 到数组 - C 语言
【发布时间】:2020-07-03 07:53:49
【问题描述】:

我尝试将 uint64_t 数组解析为 char 数组(结果为十进制,用逗号分隔)。

我使用 memcpy,每次我得到一个随机值。 iota() 函数转换最大 uint32_t 值。我尝试将 uint64_t 与 2 uint32_t 分开,但我从来没有得到正确的结果。

    uint64_t numbers[10] = { 201234567890123456, 
                           12345678901234567890, 
                           98765432109876543, 
                           65432109887, 
                           12345234512345,
                           217631276371261627,
                           12354123512453124,
                           2163521442531,
                           2341232142132321,
                           1233432112 };
    char array[1000] = "";

预期结果:

array = "201234567890123456,12345678901234567890,98765432109876543,65432109887,12345234512345,217631276371261627,12354123512453124,2163521442531,2341232142132321,1233432112"

我从this 主题尝试了 int64ToChar,但结果是:

    void uint64ToChar(char a[], int64_t n) {
         memcpy(a, &n, 10);
    }

    uint64_t number = 12345678900987654;
    char output[30] = "";

    uint64ToChar(output, number);

    Result:
    �g]T�+

感谢您的帮助。

【问题讨论】:

  • 您想使用以 10 为底的 ascii 字符打印数字的表示形式。使用 snprintf
  • 如果您显示您尝试过的代码会有所帮助。
  • 你的 uint64_t 数组初始化不会这样工作:它需要在 ={ 数据 }; 周围加上大括号。
  • P.S.数组21763127637126371627 中的第六个元素大于 64 位无符号整数。使用较小的数字。

标签: c arrays uint64 itoa


【解决方案1】:

如果所有数据在编译时都可用,那么没有明显的理由应该使用像 s*printf 这样的慢速运行时转换函数。只需在预处理器阶段完成所有操作:

#define INIT_LIST           \
  201234567890123456,       \
  12345678901234567890,     \
  98765432109876543,        \
  65432109887,              \
  12345234512345,           \
  217631276371261627,       \
  12354123512453124,        \
  2163521442531,            \
  2341232142132321,         \
  1233432112

#define STR_(...) #__VA_ARGS__
#define STR(x) STR_(x)

int main (void)
{
  uint64_t numbers[10] = { INIT_LIST };
  char array[] = STR(INIT_LIST);
  puts(array);
}

如果您想对数字之间的逗号和空格位置等进行微观管理,则可以使用“X 宏”进行更高级的替代。

请注意,12345678901234567890 太大,无法在我的 64 位系统上成为有效的有符号整数常量,最大值为 2^63 - 1 = 9.22*10^18,但此数字为 12.34*10^18。我必须将其更改为 12345678901234567890ull 才能编译该程序,因为最大数量是 18.44*10^18

【讨论】:

  • 感谢提示,但编译时不知道数据。仅为此,这是一个可变的数字数组,而不是 const。
【解决方案2】:

memcpy 函数将一个字节一个字节地从一个位置复制到另一个位置。您尝试做的是取 10 个字节的 64 位数字(仅包含 8 个字节)并将它们中的每一个重新解释为 ASCII 字符。这不仅不会给出您期望的结果,而且您​​还会通过读取对象的内存边界来调用undefined behavior

猜测函数的作用是学习 C 的一种糟糕方式。您需要阅读这些函数的文档(在 Linux 上运行“man function_name”以获取相关函数或搜索 docs.microsoft .com for MSVC)了解他们的工作。

如果您使用sprintf 函数,您可以将64 位整数转换为字符串。 %lld 标识符接受 long long int,它至少与 uint64_t 一样大。

sprintf(a, "%lld", (unsigned long long)n);

【讨论】:

  • 技术上,unsigned long long 可以表示所有 64 位值,但为了完全可移植,您应该将 uint64_t 参数转换为 sprintf(a, "%llu", (unsigned long long)n); 或使用 C99 格式化宏:sprintf(a, "%"PRIu64"", n);跨度>
【解决方案3】:

使用snpintf()转换64位数字:

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

int main() {
    uint64_t numbers[10] = { 201234567890123456, 
                             12345678901234567890, 
                             98765432109876543, 
                             65432109887, 
                             12345234512345,
                             21763127637126371627,
                             12354123512453124,
                             2163521442531,
                             2341232142132321,
                             1233432112 };
    char array[1000];
    size_t i, n = sizeof(numbers) / sizeof(numbers[0]), pos = 0;

    for (i = 0; i < n && pos < sizeof(array); i++) {
        pos += snprintf(array + pos, sizeof(array) - pos, "%"PRIu64"%s", numbers[i],
                        i < n - 1 ? "," : "");
    }
    printf("%s\n", array);
    return 0;
}

【讨论】:

  • @KamilCuk:是的,确实如此!答案修改。我一直想知道为什么这些宏没有在&lt;stdint.h&gt; 中定义。
  • 谢谢,它帮助了我一点。在 PC 上运行良好。我为嵌入式平台(ESP-IDF)编译了这段代码,我的结果是:lululululululululululululululululululu...等等。
  • @maghost:您的平台似乎存在一致性问题。尝试将"%"PRIu64"%s", numbers[i], 更改为"%llu%s", (unsigned long long)numbers[i], 或可能"%lu%s", (unsigned long)numbers[i],
  • @maghost:如果您使用 Arduino C 平台,请注意这个 C 变体与 C 有很大不同,包括其标准库中的细微缺陷。
  • @maghost:您可以编写自己的 64 位到十进制转换例程。
【解决方案4】:

您可以通过在for 循环中使用sprintf_s 来完成此操作。

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

#define BUFSIZE 22                  /* string buffer size to support a single 64 bit unsigned integer */
#define ARRSIZE 10                  /* size of the unsigned integer array */
#define STRSIZE BUFSIZE * ARRSIZE   /* max size of the string of unsigned integer array */

int main()
{
    int i;
    char num_str[STRSIZE] = "";
    uint64_t num_arr[ARRSIZE] = {
        201234567890123456,
        12345678901234567890,
        98765432109876543,
        65432109887,
        12345234512345,
        2176312763712637162,
        12354123512453124,
        2163521442531,
        2341232142132321,
        1233432112
    };

    for (i = 0; i < ARRSIZE; i++)
    {
        /* convert an unsigned integer to a string and concatenate to previous string every loop */
        sprintf_s(num_str + strlen(num_str), BUFSIZE, "%llu,", num_arr[i]);
    }

    num_str[strlen(num_str) - 1] = 0;   /* truncate the trailing comma */

    printf("%s", num_str);

    return 0;
}

这会导致:

num_str = "201234567890123456,12345678901234567890,98765432109876543,65432109887,12345234512345,2176312763712637162,12354123512453124,2163521442531,2341232142132321,1233432112"

【讨论】:

  • 如果要传递不正确的大小参数,为什么要使用sprintf_s
  • 谢谢,它帮助了我一点。我更改了 sprintf_s -> snprintf() 因为我在 Linux 上工作。在 PC 上运行良好。我为嵌入式平台(ESP-IDF)编译了这段代码,我的结果是:lu,lu,lu,lu,lu,lu,lu,lu,lu,lu
猜你喜欢
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 2020-05-12
  • 2020-08-04
  • 2017-03-18
相关资源
最近更新 更多