6.58 Встроенные функции для выполнения арифметических операций с проверкой переполнения
Следующие встроенные функции позволяют выполнять простые арифметические операции вместе с проверкой переполнения при выполнении этих операций.
-
Встроенная функция:
bool__builtin_add_overflow(type1 a, type2 b, type3 *res) -
Встроенная функция:
bool__builtin_sadd_overflow(int a, int b, int *res) -
Встроенная функция:
bool__builtin_saddl_overflow(long int a, long int b, long int *res) -
Встроенная функция:
bool__builtin_saddll_overflow(long long int a, long long int b, long long int *res) -
Встроенная функция:
bool__builtin_uadd_overflow(unsigned int a, unsigned int b, unsigned int *res) -
Встроенная функция:
bool__builtin_uaddl_overflow(unsigned long int a, unsigned long int b, unsigned long int *res) -
Встроенная функция:
bool__builtin_uaddll_overflow(unsigned long long int a, unsigned long long int b, unsigned long long int *res) -
Эти встроенные функции преобразуют первые два операнда в целые типы бесконечной точности со знаком и выполняют сложение над этими преобразованными операндами. Результат затем приводится к типу, на который указывает третий указательный аргумент, и сохраняется там. Если сохраненный результат равен результату бесконечной точности, встроенные функции возвращают
false, в противном случае они возвращаютtrue. Так как сложение выполняется в бесконечной точности со знаком, у этих встроенных функций есть полностью определенное поведение для всех значений аргументов.Первая встроенная функция допускает произвольные целочисленные типы для операндов, а тип результата должен быть указателем на некоторый целочисленный тип, кроме перечислимого или булева типа; остальные встроенные функции имеют явные целочисленные типы.
Компилятор попытается использовать аппаратные инструкции для реализации этих встроенных функций, где это возможно, например, условный переход на переполнение после сложения, условный переход на перенос и т. д.
-
Встроенная функция:
bool__builtin_sub_overflow(type1 a, type2 b, type3 *res) -
Встроенная функция:
bool__builtin_ssub_overflow(int a, int b, int *res) -
Встроенная функция:
bool__builtin_ssubl_overflow(long int a, long int b, long int *res) -
Встроенная функция:
bool__builtin_ssubll_overflow(long long int a, long long int b, long long int *res) -
Встроенная функция:
bool__builtin_usub_overflow(unsigned int a, unsigned int b, unsigned int *res) -
Встроенная функция:
bool__builtin_usubl_overflow(unsigned long int a, unsigned long int b, unsigned long int *res) -
Встроенная функция:
bool__builtin_usubll_overflow(unsigned long long int a, unsigned long long int b, unsigned long long int *res) -
Эти встроенные функции аналогичны встроенным функциям проверки переполнения сложения, описанным выше, за исключением того, что они выполняют вычитание, вычитая второй аргумент из первого, вместо сложения.
-
Встроенная функция:
bool__builtin_mul_overflow(type1 a, type2 b, type3 *res) -
Встроенная функция:
bool__builtin_smul_overflow(int a, int b, int *res) -
Встроенная функция:
bool__builtin_smull_overflow(long int a, long int b, long int *res) -
Встроенная функция:
bool__builtin_smulll_overflow(long long int a, long long int b, long long int *res) -
Встроенная функция:
bool__builtin_umul_overflow(unsigned int a, unsigned int b, unsigned int *res) -
Встроенная функция:
bool__builtin_umull_overflow(unsigned long int a, unsigned long int b, unsigned long int *res) -
Встроенная функция:
bool__builtin_umulll_overflow(unsigned long long int a, unsigned long long int b, unsigned long long int *res) -
Эти встроенные функции аналогичны встроенным функциям проверки переполнения сложения, описанным выше, за исключением того, что они выполняют умножение вместо сложения.
Следующие встроенные функции позволяют проверить, может ли простая арифметическая операция вызвать переполнение.
-
Встроенная функция:
bool__builtin_add_overflow_p(type1 a, type2 b, type3 c) -
Встроенная функция:
bool__builtin_sub_overflow_p(type1 a, type2 b, type3 c) -
Встроенная функция:
bool__builtin_mul_overflow_p(type1 a, type2 b, type3 c) -
Эти встроенные функции аналогичны
__builtin_add_overflow,__builtin_sub_overflow, или__builtin_mul_overflow, за исключением того, что они не сохраняют результат арифметической операции и последний аргумент не является указателем, а является каким-то выражением с целочисленным типом, отличным от перечислимого или булева типа.Встроенные функции преобразуют первые два операнда в типы со знаком бесконечной точности и выполняют сложение над этими преобразованными операндами. Результат затем приводится к типу третьего аргумента. Если результат преобразования равен результату бесконечной точности, встроенные функции возвращают
false, в противном случае они возвращаютtrue. Значение третьего аргумента игнорируется, просто выполняются побочные эффекты третьего аргумента, и никакие целочисленные преобразования аргументов не выполняются над последним аргументом. Если третий аргумент является полем битов, тип, используемый для приведения к результату, имеет точность и знак данного поля битов, а не точность и знак базового типа.Например, следующая макрокоманда может использоваться для проверки на этапе компиляции, произойдёт ли переполнение при сложении двух константных целых чисел, и выполнить сложение только тогда, когда это известно как безопасно, а не для выдачи предупреждения -Woverflow.
#define INT_ADD_OVERFLOW_P(a, b) \ __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) enum { A = INT_MAX, B = 3, C = INT_ADD_OVERFLOW_P (A, B) ? 0 : A + B, D = __builtin_add_overflow_p (1, SCHAR_MAX, (signed char) 0) };Компилятор попытается использовать аппаратные инструкции для реализации этих встроенных функций, например, условный переход на переполнение после сложения, условный переход на перенос и т. д.
-
Встроенная функция:
unsigned int__builtin_addc(unsigned int a, unsigned int b, unsigned int carry_in, unsigned int *carry_out) -
Встроенная функция:
unsigned long int__builtin_addcl(unsigned long int a, unsigned long int b, unsigned int carry_in, unsigned long int *carry_out) -
Встроенная функция:
unsigned long long int__builtin_addcll(unsigned long long int a, unsigned long long int b, unsigned long long int carry_in, unsigned long long int *carry_out) -
Эти встроенные функции эквивалентны:
({ __typeof__ (a) s; \ __typeof__ (a) c1 = __builtin_add_overflow (a, b, &s); \ __typeof__ (a) c2 = __builtin_add_overflow (s, carry_in, &s); \ *(carry_out) = c1 | c2; \ s; })т. е. они складывают 3 беззнаковых значения, устанавливают значение, на которое указывает последний аргумент, в 1, если какое-либо из двух сложений вызвало переполнение (в противном случае 0), и возвращают сумму этих 3 беззнаковых значений. Обратите внимание, что, хотя все первые 3 аргумента могут иметь произвольные значения, лучший код будет сгенерирован, если одно из них (предпочтительно третье) имеет только значения 0 или 1 (т. е. входной перенос).
-
Встроенная функция:
unsigned int__builtin_subc(unsigned int a, unsigned int b, unsigned int carry_in, unsigned int *carry_out) -
Встроенная функция:
unsigned long int__builtin_subcl(unsigned long int a, unsigned long int b, unsigned int carry_in, unsigned long int *carry_out) -
Встроенная функция:
unsigned long long int__builtin_subcll(unsigned long long int a, unsigned long long int b, unsigned long long int carry_in, unsigned long long int *carry_out) -
Эти встроенные функции эквивалентны:
({ __typeof__ (a) s; \ __typeof__ (a) c1 = __builtin_sub_overflow (a, b, &s); \ __typeof__ (a) c2 = __builtin_sub_overflow (s, carry_in, &s); \ *(carry_out) = c1 | c2; \ s; })т. е. они вычитают 2 беззнаковых значения из первого беззнакового значения, устанавливают значение, на которое указывает последний аргумент, в 1, если любое из двух вычитаний вызвало переполнение (в противном случае 0), и возвращают результат вычитаний. Обратите внимание, что, хотя все первые 3 аргумента могут иметь произвольные значения, более эффективный код будет сгенерирован, если одно из них (предпочтительно третье) имеет только значения 0 или 1 (т. е. входной перенос).
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-14.2.0/gcc/Integer-Overflow-Builtins.html