When #pragma first came into usage, the people behind GCC weren't able to put in support for it right away, so instead they quickly hacked in a very odd little quick-fix.
With these certain earlier versions of gcc, if you compiled a file containing a #pragma, GCC would attempt each of the following in turn:
  1. Attempt to launch a game of nethack.
  2. Attempt to launch a game of rogue.
  3. Attempt to launch a game of Towers of Hanoi via emacs.
  4. Print the message "You are in a maze of twisty compiler features, all different."
I don't think the GCC people liked the idea of #pragma very much.
The thing about #pragma is that it has no standard behavior. Oh, #pragma itself is standard, all right-- it's just the arguments you give #pragma aren't. They vary completely from compiler to compiler.

#pragma is just kind of the standard way for a compiler to give an interface to do nonstandard things-- by definition, #pragma arguments are to be interpreted in whatever arbitrary way the compiler decides. Meaning the old GCC "feature" above was not an easter egg as some have claimed, but actual support for #pragma-- just an odd implementation, that's all.

The problem with this is that it's perfectly accepted for compilers to introduce pragma directives with the same keyname but different effects-- meaning . Ariels has an excellent example of how this can get painful in #pragma is useless. This is why even today GNU tries to avoid #pragma to the greatest extent possible, using language extentions such as are described in Ariels' node and in some cases (though i can't seem to find the exact documentation) having the programmer #define specific strings in order to denote which gcc-specific compilation options they wish to use. When they do use #pragma for things, they request programmers preface their #pragma calls with "GCC" in order to prevent ugly namespace collisions and ugly ifdef cludges.


#pragma directives in Codewarrior (this list is incomplete, and will be added to when i finally find my documentation cd)
#pragma mark label
The Codewarrior IDE has this nifty little feature where all the editor windows are fitted with pop-up menus listing all the functions in the current file, sorted by location. Choose the function from the menu, and the window automatically scrolls the document to that function for you. You have no idea how addictive this feature becomes.

#pragma mark label adds an item named label to the menu; selecting label jumps you to the #pragma. You can also say #pragma mark -, which adds a divider to the menu.. meaning you can cleanly arrange your functions into logical groups within the menu.

#pragma unused variable
You put this at the beginning of a function to tell the compiler that the passed variable variable is not used in the function. Supposedly the variable is still compiled in and passed and allocated and everything-- all this directive does is disable the irritating compiler warning.


#pragma directives in gcc (These are the preprocessor-handled directives only. I'm still looking for the compiler #pragma docs.)

#pragma GCC system_header
This tells GCC to consider everything after the pragma to be system headers. The effect this is that certain types of compiler warnings, esp. the ones generated by the -pedantic flag, are ignored, under the logic that OS and runtime libraries shouldn't be expected to be strictly conforming C. You can get this same effect using the -I and -isystem compiler flags; see the manpage.

This directive has no effect in the primary source file (main()?); it only works on #included files.

#pragma GCC poison identifiers
This directive bans usage of the identifiers within the program. Poisoned identifiers cannot be #ifdef'd or #undef'd, and attempting to use them for anything will produce an error. Identifiers is a list, separated by spaces.
#pragma GCC dependency "filename" message
If file filename is newer than the file containing this #pragma, a warning is issued containing the error message message.

The "gcc" in each of the above is part of the namespacing in the C99 standard. For backwards compatibility reasons, the gcc can be left out, but it shouldn't be.

gcc info gathered from http://www.gnu.org/software/gcc/onlinedocs/cpp_1.html

C's #pragma exists so we can pass various nonstandard information to the C compiler. As alluded to above, it isn't necessarily well-liked by compilerers. Why not? After all, there are lots of good reasons to want to communicate some nonstandard information to your C compiler. If this information is not necessary to compile the program, but only to reduce warnings or produce better code, why not use #pragma?

On its own, #pragma isn't standard enough to be useful

Of course. It's meant for nonstandard features. Only most "nonstandard" features will still be supported by almost all compilers. And each will do it differently.

Let's look at a typical example. Many C compilers support inlining of functions (at least within the same source filecompilation unit). Some heuristics are used to determine inlinability, but you might want to override them. Surely we can use #pragma to do it!

Well, almost.

  • SGI's C compiler lets you say #pragma inline global function (as well as some more complex options to fine-tune the inlining) to inline function wherever it appears. If you say just #pragma inline function then inlining occurs only within that scope.
  • Sun's Forte C compiler lets you say #pragma inline function. It has fewer options than SGI's #pragma inline (SGI is more of a supercomputing company than Sun). In fairness, judicious placement of #pragma inline can yield the same intended effect in both compilers, as long as you just want expansion throughout the file. The #pragma must appear after the function has already been declared.
  • Compaq's C compiler requires brackets around the function names. Luckily, the brackets do no harm in the other 2 compilers.
By sheer luck, the form #pragma inline (function), placed after the function has already been declared, works on all 3 compilers. Except if it's not in the top-most scope, in which case it will have different semantics on SGI. And if our function is recursive, we'll have to predeclare it then #pragma inline it to get one level of recursion inlined on all our platforms.

Dealing with compiler dependencies

The way to deal with compiler dependencies like this (and they are unavoidable) is to use #ifdef to determine which compiler we're using. So we could say

/* Define function, then ... */
#ifdef __sgi
#pragma inline global function
#elif defined(__alpha)
#pragma inline (function)
#elif defined(__sun)
#pragma inline function
#endif
which has a fighting chance of being understood by an experienced user of the compiler on her native platform.

Abstracting #ifdefs away

The code above is a maintenance nightmare. If we want to add support for the new ariel Si Si compiler, we have to add a #elif clause on every inlining. The solution to this is abstraction: create some higher level construct INLINE(function) and use that instead. The definition of the construct will use #ifdefs, but they'll all be in one spot, and easy to maintain and modify.

Presumably, INLINE will be a macro, and we'll #define it appropriately.

Excuse me, did someone say "macro"? Because you cannot standardly use macros and preprocess constructs. And anything beginning with # belongs to the preprocessor.

So there is no maintainable way to use #pragmas in your code.

Epilogue

  1. You C++ weenies in the corner can stop snickering RIGHT NOW! The inlining example was just that. C++ has #pragmas just like C has them, and they are no better for when you need them.
  2. The alternative? Do like the gcc (GNU) people do, and ignore that part of the ISO C standard (it is standard-conforming to do whatever takes your fancy with #pragma). Instead, introduce new reserved keywords such as __inline__ (anything which begins with two underscores is part of the implementation namespace, so this too is standard-conforming). This can be used portably:
    #ifdef __gcc
    #define INLINE(f) __inline__(f)
    #else
    #define INLINE(f)
    #endif
    

Log in or register to write something here or to contact authors.