Spec-Zone.ru › GCC 15

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API