Трюк #ifndef/#define/#endif работает на любом компиляторе C, и на некоторых из них он ускоряет процесс компиляции. Трюк #pragma является нестандартным, и работает только в некоторых компиляторах Си, и может привести к другой семантике в тех, которые его не поддерживают.
Разница в том, что последняя - это C, а первая - нет. Никогда не используйте #pragma once
; всегда используйте #ifndef
.
Еще одна вещь, которую следует отметить при использовании метода #ifndef
, заключается в том, что любой символ препроцессора, начинающийся с двух подчеркиваний или подчеркивания, за которым следует заглавная буква, является зарезервированным и не может быть использован. Вы должны использовать такие вещи, как #ifndef MYHEADER_H
и не #ifndef _MYHEADER_H
.
Используйте #pragma
, когда вы обращаетесь к конкретному компилятору (или набору совместимых компиляторов), чтобы направить его генерацию кода, или если вы используете стандартизированную #pragma
, такую как FP_CONTRACT
или -... CX_LIMITED_RANGE-
, которые поддерживает любой компилятор, соответствующий стандартам.
Используйте #ifndef
и ilk, если вы обращаетесь к стандартному препроцессору C (или C++) и хотите, чтобы ваш код был переносимым во всех компиляторах, соответствующих стандартам.
Использование любой #pragma
, которая не определена в стандарте C (или C++), делает ваш код не переносимым. #pragma once
является некоторым исключением, поскольку это одна из наиболее часто реализуемых нестандартных конструкций #pragma
. Однако ее реализация не является универсальной для компиляторов, соответствующих стандартам. #ifndef
является.
Конструкция
#ifndef MYFOO_H
#define MYFOO_H
/* header information for myfoo.h */
#endif
должна быть в каждом заголовочном файле. Фокус в том, что вы можете включить заголовочный файл (случайно) более одного раза, не задумываясь о двойных объявлениях. так что это для препроцессора.
#pragma - для компилятора, а препроцессор должен игнорировать прагмы, которые он не понимает.