Preprocessor directives
=======================
Preprocessing is the first steps of the C translation process.
1. Trigraph replacement (trigraph characters are replaced).
2. Line splicing (lines ending with escaped newlines are spliced).
3. Tokenization (and replacing comments with whitespace).
4. Macro expansion and directive handling.
Digraphs and trigraphs
----------------------
The required character set of the programming language and the usual
input devices (e.g. keyboard) may differ.
Not only in C, Pascal supports digraphs:
(. --> [
.) --> ]
(* --> {
*) --> }
C language trigraphs:
??= --> #
??/ --> \
??' --> ^
??( --> [
??) --> ]
??! --> |
??< --> {
??> --> }
??- --> ~
printf("How are you??-I am fine") --> printf("How are you~I am fine")
printf("How are you???-I am fine") --> printf("How are you?~I am fine")
a++; -->
/??/
* A comment *??/
/ -->
Digraphs (from C99) handled in tokenization (step 4.)
<: --> [
:> --> ]
<% --> {
%> --> }
%: --> #
Preprocessor directive handling
-------------------------------
#include <filename>
Search filename in the standard compiler include path
#include "filename"
Search filename in the current source directory
$ g++ -I/usr/local/include/add/path1 -I/usr/local/include/add/path2 ...
Extend the include path from command line
The preprocessor replaces the line with the text of the "filename".
#include <stdio.h>
int main(void)
{
printf("Hello, world!\n");
return 0;
}
Macro definition
-----------------
#define <identifier> <token-list>
Object-like macro
#define BUFSIZE 1024
#define PI 3.14159
#define USAGE_MSG "Usage: command -flags args..."
#define LONG_MACRO struct MyType \
{ \
int data; \
};
Usage:
char buffer[BUFSIZE];
fgets(buffer, BUFSIZE, stdin);
#define <identifier>(<param-list>) <token-list>
Function-like macro
#define FAHR2CELS(x) ((5./9.)*(x-32))
#define MAX(a,b) ((a) > (b) ? (a) : (b))
Usage:
c = FAHR2CELS(f);
x = MAX(x,-x);
x = MAX(++y,z);
#undef BUFSIZE
Conditional cmpilation
----------------------
#if DEBUG_LEVEL > 2
fprint("program was here %s %d\n", __FILE__, __LINE__);
#endif
#ifdef __unix__
# include <unistd.h>
#elif defined _WIN32
# include <windows.h>
#endif
#if !(defined( __unix__ ) || defined (_WIN32) )
#else
#endif
Error
-----
#if RUBY_VERSION == 190
# error 1.9.0 not supported
#endif
Line
----
#line 567
Header guards
-------------
To avoid multiple inclusion:
#ifndef MY_HEADER_H
#define MY_HEADER_H
#endif
Alternative solution:
#pragma ones
Standard defined Macros
-----------------------
__FILE__
__LINE__
__DATE__
__TIME__
__STDC__
__STDC_VERSION__
__cplusplus
#ifdef __cplusplus
extern C {
#endif
Pragma
------
#pragma warning(disable:4786)
Token stringification
---------------------
#define str(s) #s
#define BUFSIZE 1024
str(\n) --> "\n"
str(BUFSIZE) --> 1024
Token concatenation
-------------------
struct my_int_20_array
{
int v[20];
};
struct my_int_30_array
{
int v[30];
};
struct my_double_40_array
{
double v[40];
};
#define DECLARE_ARRAY(NAME, TYPE, SIZE) \
typedef struct TYPE##_##SIZE##_array \
{ \
TYPE v[SIZE]; \
\
} NAME##_t;
DECLARE_ARRAY(yours,float,10);
yours_t x, y;