Почему g cc не вызывает функцию abs? - PullRequest
1 голос
/ 05 марта 2020

У меня есть код C

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

int32_t abs(int32_t x) {

        int32_t mask = (x >> 31);
        printf("mask is %d\n",mask);
        return (x + mask) ^ mask;

}
int main(int argc, char *argv[])
{
        int32_t i=-5;
        printf("%d\n",abs(i));

        return 0;
}

, и я компилирую его с помощью G CC.

g cc -O0 -S -masm = intel

Код asm находится в https://pastebin.com/4TGpSsdd

Почему g cc не вызывает функцию abs, а clang делает.

Программа не вызывает функция abs и

выполнение кода 「printf (« mask is% d \ n », mask);」

My g cc версия:

g cc (Ubuntu 4.8.4-2ubuntu1 ~ 14.04.3) 4.8.4

Это ошибка ag cc?

Ответы [ 4 ]

2 голосов
/ 05 марта 2020

abs - это встроенная в G CC, но Clang заменяет встроенные функции вызовами соответствующих библиотечных функций.

Чтобы исправить это, вы можете переименовать вашу функцию (которая рекомендуется; см. ниже обоснование) вы можете скомпилировать свой код, используя -fno-builtin-abs, или вы можете пометить свою функцию как static.

Вот цитата со связанной страницы:

Функции ISO C90 abort, abs, acos, [...] и vsprintf все распознаются как встроенные функции, если не указано -fno-builtin (или -fno-builtin-<i>function</i> не указано для индивидуальная функция). Все эти функции имеют соответствующие версии с префиксом __builtin_.

. Стандарт C гласит, что переопределение библиотечных функций с помощью external является неопределенным поведением (C11 §7.1.3 1):

Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотеки) и errno всегда зарезервированы для использования в качестве идентификаторов с внешней связью.

Если вы определите abs как static, звонок не будет удален.

1 голос
/ 05 марта 2020

Это ошибка ag cc?

Нет.

abs - это функция, определенная в стандарте C, ее прототип представлен как int abs (int) by #include <stdlib.h>.

Однако, даже без включения этого заголовка, g cc обладает встроенными знаниями о abs и знает, что он должен делать. Это относится к хосту C, который используется большинством пользователей.

В не хосте C однако компилятор не должен делать никаких предположений относительно семантики функций, объявленных в стандартных заголовках. В g cc вы получаете не колеблясь, соотв. отдельно -freestanding.

Кроме того, даже без включенной оптимизации (-O0), g cc будет складывать константы. Это связано с тем, что в

int x = 1 + 2;

вы не можете выполнить инициализацию во время выполнения для x в хранилище stati c - в отличие от C ++, который может инициализировать это во время выполнения в принципе. В вашем случае

abs (-5)

складывается в 5.

Поскольку вы, скорее всего, не хотите использовать -ffreestanding, вы можете использовать -fno-builtin-abs, чтобы убрать встроенный знание о abs, то же самое для многих других функций. Даже с опцией -fno-builtin-abs вы можете использовать __builtin_abs в своем коде, если вы предпочитаете оптимизированную версию вычисления абсолютного значения, а не libcall, libc.a / libc.so.


Приложение Отдельно стоящее объявление из-за комментария: C99 §4 Соответствие, говорит:

Две формы соответствующей реализации размещены и автономны. соответствующая размещенная реализация принимает любую строго соответствующую программу. соответствующая автономная реализация должна принимать любую строго соответствующую программу, которая не использует сложные типы и в которой использование функций, указанных в разделе библиотеки (пункт 7), ограничено содержимым стандартных заголовков <float.h>, <iso646.h>, <limits.h>, <stdarg.h>, <stdbool.h>, <stddef.h> и <stdint.h>.
1 голос
/ 05 марта 2020
  1. не используйте стандартное имя функции. Многие функции (включая abs) хорошо известны компилятору g cc. Они называются встроенными. Таким образом, компилятор знает, что делает эта функция, и во многих случаях ему не нужно вызывать ее.

Если вы переименуете ее - он сгенерирует вызов с -O0 https://godbolt.org/z/dLg26U

Если вы хотите, чтобы он вызывался, если вы включаете оптимизацию, вы должны указать компилятору не вставлять его. https://godbolt.org/z/aHaEik

 int32_t __attribute__((noinline)) myabs(int32_t x) {
1 голос
/ 05 марта 2020

В stdlib.h есть функция int abs(int x).

Вам необходимо переименовать вашу функцию.

...