Подтвердить что ты не робот

Назначение 128-битного целого числа в C

Когда я пытаюсь назначить целое число 128 бит в gcc 4.9.1, я получаю warning: integer constant is too large for its type.

Пример кода

int main(void) {
  __uint128_t p = 47942806932686753431;

  return 0;
}

Выход

Я компилирую с gcc -std=c11 -o test test.c, и я получаю:

test.c: In function ‘main’:
test.c:2:19: warning: integer constant is too large for its type
   __uint128_t p = 47942806932686753431;
               ^

Я делаю что-то неправильно или это ошибка в gcc?

4b9b3361

Ответ 1

Я делаю что-то неправильно или это ошибка в gcc?

Проблема в части 47942806932686753431, а не в __uint128_t p. Согласно gcc docs нет возможности объявить 128-битную константу:

В GCC нет поддержки для выражения целочисленной константы типа __int128 для целей с длинным длинным целым размером менее 128 бит.

Итак, кажется, что, хотя вы можете иметь 128-битные переменные, вы не можете иметь 128-битных констант, если ваш long long не имеет ширины 128 бит.

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

Ответ 2

Вы пробовали это?

__int128 p = *(__int128*) "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";

EDIT 25 ноября

Извините за плохое разъяснение в предыдущем посте. Серьезно, я не публиковал этот ответ как шутку. Хотя в документе GCC нет возможности выразить 128-битную целочисленную константу, это сообщение просто предоставляет обходное решение для тех, кто с легкостью присваивает значения __uint128_t переменным.

Вы можете попытаться скопировать код ниже с помощью GCC (7.2.0) или Clang (5.0.0). Он печатает желаемые результаты.

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

int main()
{
    __uint128_t p = *(__int128*) "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
    printf("HIGH %016llx\n", (uint64_t) (p >> 64));
    printf("LOW  %016llx\n", (uint64_t) p);
    return 0;
}

Стандартный вывод:

HIGH 0f0e0d0c0b0a0908
LOW  0706050403020100

Это рассматривается только как обходное решение, так как оно играет трюки на указателях, помещая "значение" в раздел .rodata(если вы objdump его), и он не переносится (x86_64 и aarch64 в порядке, но не в руке и x86). Я думаю, этого достаточно для кодирования на настольных компьютерах.