Как объединить два 32-разрядных целых числа в одно 64-разрядное целое число?

У меня есть регистр количества, который составлен из двух 32-разрядных целых чисел без знака, один для более высоких 32 битов значения (старшее значащее слово), и другой для более низких 32 битов значения (младшее значащее слово).

Каков лучший способ в C, чтобы объединить эти два 32-разрядных целых числа без знака и затем отобразиться как большое количество?

В определенном:

leastSignificantWord = 4294967295; //2^32-1

printf("Counter: %u%u", mostSignificantWord,leastSignificantWord);

Это распечатало бы прекрасный.

Когда число увеличено к 4294967296, у меня есть оно так очистки leastSignificantWord к 0, и mostSignificantWord (0 первоначально) равняется теперь 1. Целый счетчик должен теперь читать 4294967296, но прямо сейчас он просто читает 10, потому что я просто конкатенирую 1 от mostSignificantWord и 0 от leastSignificantWord.

Как я должен заставить его отобразиться 4294967296 вместо 10?

22
задан Joe 4 May 2010 в 20:53
поделиться

4 ответа

long long val = (long long) mostSignificantWord << 32 | leastSignificantWord;
printf( "%lli", val );
35
ответ дан 29 November 2019 в 03:21
поделиться

В этом случае может быть выгодно использовать целые числа без знака с явными размерами:

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

int main(void) {
  uint32_t leastSignificantWord = 0;
  uint32_t mostSignificantWord = 1;
  uint64_t i = (uint64_t) mostSignificantWord << 32 | leastSignificantWord;
  printf("%" PRIu64 "\n", i);

  return 0;
}
Выход { {1}}

4294967296

Структура (uint64_t) mostSignificantWord << 32 | lessSignificantWord

left logical shift

61
ответ дан 29 November 2019 в 03:21
поделиться

мой вариант:

unsigned int low = <SOME-32-BIT-CONSTRANT>
unsigned int high = <SOME-32-BIT-CONSTANT>

unsigned long long data64;

data64 = (unsigned long long) high << 32 | low;

printf ("%llx\n", data64); /* hexadecimal output */
printf ("%lld\n", data64); /* decimal output */

Другой подход:

unsigned int low = <SOME-32-BIT-CONSTRANT>
unsigned int high = <SOME-32-BIT-CONSTANT>

unsigned long long data64;
unsigned char * ptr = (unsigned char *) &data;

memcpy (ptr+0, &low, 4);
memcpy (ptr+4, &high, 4);

printf ("%llx\n", data64); /* hexadecimal output */
printf ("%lld\n", data64); /* decimal output */

Обе версии работают, и у них будет схожая производительность (компилятор оптимизирует memcpy).

Вторая версия не работает с целевыми числами с прямым порядком байтов, но в ней нет необходимости гадать, должна ли константа 32 быть 32 или 32ull. Что-то я никогда не уверен, когда вижу сдвиги с константами больше 31.

3
ответ дан 29 November 2019 в 03:21
поделиться

Вместо того, чтобы печатать десятичное число, я часто печатаю в шестнадцатеричном.

Таким образом ...

printf ("0x%x%08x\n", upper32, lower32);

В качестве альтернативы, в зависимости от архитектуры, платформы и компилятора, иногда можно обойтись чем-то вроде ...

printf ("%lld\n", lower32, upper32);

или

printf ("%lld\n", upper32, lower32);

Однако этот альтернативный метод сильно зависит от машины (endian -ness, а также 64 vs 32 бит, ...) и вообще не рекомендуется.

Надеюсь, это поможет.

1
ответ дан 29 November 2019 в 03:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: