2010-05-09 2 views
28

чистый - это атрибут функции, который говорит о том, что функция не модифицирует глобальную память.
const - это атрибут функции, который гласит, что функция не считывает и не изменяет какую-либо глобальную память.атрибуты функции pure/const в разных компиляторах

Учитывая эту информацию, компилятор может выполнить некоторые дополнительные оптимизации.

Пример для GCC:

float sigmoid(float x) __attribute__ ((const)); 

float calculate(float x, unsigned int C) { 
    float sum = 0; 
    for(unsigned int i = 0; i < C; ++i) 
     sum += sigmoid(x); 
    return sum; 
} 

float sigmoid(float x) { return 1.0f/(1.0f - exp(-x)); } 

В этом примере компилятор может оптимизировать функцию высчитывает к:

float calculate(float x, unsigned int C) { 
    float sum = 0; 
    float temp = C ? sigmoid(x) : 0.0f; 
    for(unsigned int i = 0; i < C; ++i) 
     sum += temp; 
    return sum; 
} 

Или, если ваш компилятор достаточно умен (а не так строги плавает):

float calculate(float x, unsigned int C) { return C ? sigmoid(x) * C : 0.0f; } 

Как я могу отметить fu таким образом, для разных компиляторов, т. е. GCC, Clang, ICC, MSVC или других?

+1

Для тех из нас, кто не использует gcc на регулярной основе, возможно, вы можете опубликовать объяснение того, что такое атрибут pure/const. Если это какая-то оптимизация, полезен пример кода C или C++, для которого он помогает компилятору генерировать более оптимальную сборку. –

+0

Я не автор компилятора, но мне кажется, что такой атрибут был бы лишним, если бы определение функции 'sigmoid()' было доступно компилятору * перед * анализом 'calculate()' в той же самой единицы перевода. Несмотря на это, эти атрибуты могут быть полезны, когда определения функций находятся в разных единицах перевода. – Void

+0

Да, GCC (и другие компиляторы) автоматически автоматически добавляет этот атрибут именно в этом случае. А затем, основываясь на атрибуте, они могут делать дальнейшие оптимизации (как в моем примере).И вы точно удалили одну из основных причин для ее указания явно: если компилятор не видит определения в этой точке или если определение не доступно вообще или если вы считаете, что это безопасно, если компилятор уменьшает количество вызывает функцию. – Albert

ответ

26

В целом кажется, что почти все компиляторы поддерживают атрибуты GCC. MSVC до сих пор является единственным компилятором, который их не поддерживает (и который также не имеет альтернативы).

+1

MSVC также не имеет намерения добавлять поддержку для этих атрибутов: https://connect.microsoft.com/VisualStudio/feedback/details/804288/msvc-add-const-and-pure-like-function-attributes. Они говорят, что им это не нужно, что имеет смысл для приложений, но не для библиотек. – bcmpinc

+2

Подумайте о GNU C в качестве языкового диалекта или набора языковых расширений. Вы можете проверить наличие конкретной функции GNU C в любом компиляторе, используя '#if __GNUC__> 4 || ... "или аналогично, как рекомендовано [в руководстве] (https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html). Clang (и другие компиляторы) рекламируют только версии '__GNUC__' и' __GNUC_MINOR__', которые они полностью поддерживают. Реализация может отличаться от gcc (например, clang '__builtin_constant_p()' не распространяется на const-ness в функции args встроенных функций), но ваш код будет скомпилирован. –

+1

Другими словами, clang и ICC могут поддерживать новую функцию от gcc 6.0, но будут определять только '__GNUC__' до 6 и' __GNUC_MINOR__' до 0 в версиях, поддерживающих * все * расширения языка, которые gcc6.0 делает. –

Смежные вопросы