Почему в g++ std:: intmax_t не является __int128_t?

Мой вопрос довольно прост: поскольку std::intmax_t определяется как maximum width integer type в соответствии с cppreference, почему он не соответствует __int128_t в GCC?

Ответ 1

Я считаю, что это нарушение стандартов C и С++ - либо это, либо gcc не считает, что __int128_t является целым типом.

Стандарт C (как выпуски 1999 г., так и 2011 г.) не требует, чтобы intmax_t был одним из стандартных типов; он должен быть "объявленным целочисленным типом, способным представлять любое значение любого целочисленного типа со знаком". В частности, это может быть расширенный целочисленный тип - и если существует 128-разрядный расширенный целочисленный тип, то intmax_t должен иметь ширину не менее 128 бит.

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

В стандарте С++ 2011 используется функция расширенных целочисленных типов C99 и отсылается к стандарту 1999 C для определения intmax_t и <stdint.h>.

Итак, если __int128_t является целым типом в значении, определенном стандартом (что, безусловно, может быть), и, как следует из названия, имеет ширину 128 бит, тогда intmax_t должно быть не менее 128 бит.

Как Ответ Стивена Canon, изменение intmax_t требует некоторой работы. Стандарты C и С++ не признают это как оправдание неправильного определения intmax_t.

Конечно, все это в равной степени относится к uintmax_t.

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

int main(void) {
    __uint128_t huge = UINTMAX_MAX;
    huge ++;
    if (huge > UINTMAX_MAX) {
        puts("This should not happen");
    }
}

В моей системе (Linux x86_64, gcc 4.7.2) вышеуказанная программа печатает:

This should not happen

Если gcc соответствует стандарту, то это должно быть возможно только в том случае, если __int128_t не является целым типом, но цитирует gcc 4.8.2 руководство (выделено мной):

В качестве расширения поддерживается целочисленный скалярный тип __int128 для цели, которые имеют целочисленный режим, достаточно широкий для хранения 128 бит. Просто напишите __int128 для подписанного 128-битного целого числа или unsigned __int128для неподписанного 128-битного целого. В GCC нет поддержки для выражения целого числа константа типа __int128 для целей с long long целое число менее 128 бит.

Я полагаю, можно утверждать, что фраза "как расширение" позволяет gcc отключиться отсюда, оправдывая существование __int128_t в соответствии с пунктом 6 раздела 4 стандарта:

Соответствующая реализация может иметь расширения (включая дополнительные библиотечные функции) при условии, что они не изменяют поведение каких-либо строго соответствующая программа.

а не в соответствии с разделом 6.2.6, пункт 4:

Также может быть реализовано расширенное целое число с расширенной поддержкой реализации типы.

(Я лично считаю, что создание intmax_t, по крайней мере, столь же широкого, как __int128_t, если оно существует, будет больше соответствовать намерению стандарта, даже если он (едва ли) может утверждать, что он не " t нарушает букву стандарта.)

Ответ 2

Изменение intmax_t требует не только изменений в компиляторе, но и многочисленных стандартных функций библиотеки, которые должны принимать аргументы intmax_t (а также ABI платформы могут также определять intmax_t). Компилятор может в одностороннем порядке предоставить __int128_t в качестве расширения, но он не может в одностороннем порядке изменить тип intmax_t. Для этого требуется поддержка всех стандартных реализаций библиотек, на которые нацелен компилятор.

Ответ 3

__ int128 недостаточно функциональен для использования в качестве intmax_t

Заголовок stdint.h должен содержать определение INTMAX_C (9999999999999999999999) Этот параметр позволяет вводить константу в источник C для любого значения до максимального размера типа.

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

Поэтому он не может использоваться для intmax_t.