7.2.5 Встроенные функции для выполнения арифметических операций с проверкой переполнения
Следующие встроенные функции позволяют выполнять простые арифметические операции и одновременно проверять, не произошло ли переполнение.
-
Встроенная функция:
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; })то есть они складывают три беззнаковых значения, устанавливают значение, на которое указывает последний аргумент, равным 1, если при любом из двух сложений произошло переполнение (в противном случае — 0), и возвращают сумму этих трёх беззнаковых значений. Обратите внимание: хотя все первые три аргумента могут иметь произвольные значения, более эффективный код будет сгенерирован, если один из них (предпочтительно третий) принимает только значения 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; })то есть они вычитают два беззнаковых значения из первого беззнакового значения, устанавливают значение, на которое указывает последний аргумент, равным 1, если при любом из двух вычитаний произошло переполнение (в противном случае — 0), и возвращают результат вычитаний. Обратите внимание: хотя все первые три аргумента могут иметь произвольные значения, более эффективный код будет сгенерирован, если один из них (предпочтительно третий) принимает только значения 0 или 1 (то есть входящий перенос).
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Integer-Overflow-Builtins.html