简体   繁体   中英

uint64_t to an array - C language

I tried to parse uint64_t array to an array of char (result in decimal, separated by comma).

I used memcpy, every time I get a random values. iota() function converts max uint32_t values. I tried separate uint64_t to 2 uint32_t, but I never get a right result.

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

Expected result:

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

I tried int64ToChar from this topic, but result is:

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

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

    uint64ToChar(output, number);

    Result:
    �g]T�+

Thanks for any help.

Ue snpintf() to convert the 64-bit numbers:

#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;
}

If all the data is available at compile-time, there's no obvious reason why you should use slow run-time conversion functions like s*printf. Simply do it all at pre-processor stage:

#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);
}

More advanced alternatives with "X macros" are possible, if you want to micro-manage comma and space placement between numbers etc.

Please note that 12345678901234567890 is too large to be a valid signed integer constant on my 64 bit system, the max is 2^63 - 1 = 9.22*10^18 but this number is 12.34*10^18 . I have to change it to 12345678901234567890ull to get this program to compile, since the maximum number is then 18.44*10^18 .

You can accomplish this by using sprintf_s in a for loop.

#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;
}

This results in:

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

The memcpy function copies byte by byte from one location to another. What you're attempting to do is take 10 bytes of a 64 bit number (which only contains 8 bytes) and reinterpret each of them as an ASCII character. Not only will this not give the results you expect, but you also invoke undefined behavior by reading past the memory bounds of an object.

Guessing at what functions do is a bad way to learn C. You need to read the documentation for these functions (run "man function_name" on Linux for the function in question or search docs.microsoft.com for MSVC) to understand what they do.

If you use the sprintf function, you can convert a 64 bit integer to a string. The %lld identifier accepts a long long int , which is at least as big as a uint64_t .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM