Назначение 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?
Ответы
Ответ 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). Я думаю, этого достаточно для кодирования на настольных компьютерах.