Preprocessor directives in C

Language  C  Programming 

 27 Ağustos 2021 - Türkiye



Follow
Follow
Follow

44 dakikalık okuma

The C preprocessor

The C preprocessor is a macro processor that the C compiler automatically uses to convert your program before it is actually compiled. It’s called a macro processor because you can define macros, which are short abbreviations for longer constructs.

Before a C program is compiled in a compiler, the source code is processed by a program called a preprocessor. This process is known as preprocessing. Instructions used in the preprocessor are called preprocessor directives and begin with the “#” symbol.

The following is the list of preprocessor directives offered by the C programming language.

Macro syntax: #define This macro defines a constant value and can be one of the basic data types.

Include header file Syntax: #include “file_name” The source code of the file “file_name” is included in the main program at the specified location.

Conditional compilation Syntax: #ifdef, #endif, #if, #else, #ifndef The command set is included or excluded in the source program before compilation with regard to the condition.

Other directives Syntax: #undef, #pragma #undef is used to override the definition of a defined macro variable. #Pragma is used to call a function before and after the main function in a C program.

a C program is involved in various processes. The following diagram will help you understand all of the processes a C program encounters.

pre processing

Defining and Extending Macros

A macro name is an abbreviation and means some related lines of code. Macros are useful for the following purposes:

· Simplifying and reducing repetition coding

· Reducing errors through repetition coding

· To make an assembly language program more readable.

A macro consists of a name, a number of formal parameters, and a body of code. The use of a macro name with a set of actual parameters is replaced by a code generated from its body. This is called macro expansion.

Macros allow a programmer to define pseudo-operations, typically operations that are generally desirable, are not implemented as part of the processor instruction, and can be implemented as a sequence of instructions. Each use of a macro generates new program instructions; the macro has the effect of automating the writing of the program.

Macro definition and Expansion

The name of a macro is an abbreviation for the number of lines of code associated. Macros are useful for the following purposes:

· Simplify and reduce repetitive coding

· Reduce errors caused by repetitive coding

· Make the assembly program easier to read.

A macro consists of a name, a set of formal parameters and the content of a code. The use of a macro name with an actual set of parameters is overridden by some code generated by its content. This is called macro expansion.

Macro definition

#define MACRO_NAME(arg1, arg2, ...) [code to expand to]

Macros allow the programmer to define pseudo-operations, which are often desired operations that are not executed as part of a processor instruction, but can be executed as a sequence of instructions. Each time the use of the macro will generate new program instructions, the macro has the effect of automating the writing of the program.

Macros can be defined in many programming languages ​​such as C, C ++, etc. Example Macros in C Programming Macros are commonly used in C to define small chunks of code. If the macro has parameters, they are replaced in the body of the macro during expansion; therefore, a macro in C can mimic a function in C. This is usually done to avoid the overhead of a function call in simple cases where the code is light enough that the overhead of function calls has a significant impact on performance.

For example,

#define max (a, b) a>b? A: b

Defines the macro max, taking two arguments a and b. This macro may be called like any C function, using identical syntax. Therefore, after preprocessing

z = max(x, y);

Becomes z = x>y? X:y;

While this use of macros is very important for C, for instance to define type-safe generic data-types or debugging tools, it is also slow, rather inefficient, and may lead to a number of pitfalls.

C macros are capable of mimicking functions, creating new syntax within some limitations, as well as expanding into arbitrary text (although the C compiler will require that text to be valid C source code, or else comments), but they have some limitations as a programming construct. Macros which mimic functions, for instance, can be called like real functions, but a macro cannot be passed to another function using a function pointer, since the macro itself has no address. A macro call results in macro expansion. During macro expansion, the macro statement is replaced by sequence of assembly statements.

Macro Expansion.

https://c-handbook.bitbucket.io/

A macro call leads to macro expansion. During macro expansion, the macro statement is replaced by sequence of assembly statements.

In the above program a macro call is shown in the middle of the figure. i.e. INITZ. Which is called during program execution? Every macro begins with MACRO keyword at the beginning and ends with the ENDM (end macro).whenever a macro is called the entire is code is substituted in the program where it is called. So the resultant of the macro code is shown on the right most side of the figure. Macro calling in high level programming languages

(C programming)

#define max(a,b) a>b?a:b

Main () {

int x , y;

x=4; y=6;

z = max(x, y); }

The above program was written using C programming statements. Defines the macro max, taking two arguments a and b. This macro may be called like any C function, using identical syntax. Therefore, after preprocessing

Becomes z = x>y ? x: y;

After macro expansion, the whole code would appear like this.

#define max(a,b) a>b?a:b

main()

{ int x , y;

x=4; y=6;z = x>y?x:y; }

While this use of macros is extremely important for C, for example to define type-safe generic data-types or debugging tools, it’s also slow, rather inefficient, and should cause variety of pitfalls.

C macros are capable of mimicking functions, creating new syntax within some limitations, also as expanding into arbitrary text (although the C compiler would require that text to be valid C ASCII text file , alternatively comments), but they need some limitations as a programming construct. Macros which mimic functions, for example , are often called like real functions, but a macro can’t be passed to a different function employing a function pointer, since the macro itself has no address.

In programming languages, like C or programming language , a reputation that defines a group of commands that are substituted for the macro name wherever the name appears during a program (a process called macro expansion) when the program is compiled or assembled. Macros are almost like functions therein they will take arguments and therein they’re calls to lengthier sets of instructions. Unlike functions, macros are replaced by the particular commands they represent when the program is ready for execution. function instructions are copied into a program just one occasion .

Any preprocessing tokens (macro constants or expressions) are permitted as arguments.

Directives, Macros and Options

#assert	
#cpu	
#define	
#elif	
#else	
#error	
#ident	
#if	
#ifdef	
#ifndef	
#import	
#include	
#include_next	
#line	
#machine	
#pragma	
#pragma once	
#system	
#unassert
#warning

- Invoking the C Preprocessor

-$	
-A	
-ansi	
-C	
-D	
-dD	
-dI	
-dM	
-gcc	
-H	
-I	
-idirafter	
-imacros	
-include	
-iprefix	
-isystem	
-iwithprefix	
-lint	
-M	
-MD	
-MM	
-MMD	
-nostdinc	
-nostdinc++	
-P	
-pedantic	
-pedantic-errors	
-remap	
-std	
-traditional	
-trigraphs	
-U	
-undef	
-Wall	
-Wcomment	
-Wtraditional	
-Wtrigraphs	
-Wundef	
-x assembler-with-cpp	
-x c	
-x objective-c	

_ Standard Predefined Macros

__BASE_FILE__	
__CHAR_UNSIGNED__	
__cplusplus	
__DATE__	
__FILE__	
__GNUC__	
__GNUC_MINOR__	
__GNUG__	
__INCLUDE_LEVEL__	
__LINE__	
__OPTIMIZE__	
__REGISTER_PREFIX__	
__STDC__	
__STDC_VERSION__	
__STRICT_ANSI__	
__TIME__	
__USER_LABEL_PREFIX__	
__VERSION__	
_AM29000
_AM29K

Preprocessor operators

Stringizing operator (#) 

Causes the corresponding actual argument to be enclosed in double quotation marks

Token-pasting operator (##) 

Allows tokens used as actual arguments to be concatenated to form other tokens

compilation processing

Using Header Files

Header files serve two purposes.

The system header file declares the interfaces for parts of the operating system. You include them in your program to provide the definitions and declarations needed to invoke system calls and libraries.

Your own header files contain interface declarations between the source files of your program. Whenever you have a group of related macro declarations and definitions, all or most of which are needed in several different source files, you must create a header file for them.

Including a header file produces the same results when compiling C as copying a header file into each source file that needs it. But this copying is time consuming and error prone. In the header file, the corresponding statements appear in one place.If they need to be changed, they can be changed in one place, and programs that include the header file will automatically use the new version the next time they are recompiled. The header file eliminates the work of finding and modifying all duplicates, as well as the risk. that failure to find a copy leads to inconsistencies in the program.

Usually header files are named with the extension .h. Avoid unusual characters in header file names as they reduce portability.

#include directive (C/C++)

Tells the preprocessor to include the contents of a specified file at the point where the directive appears.

Syntax

#include " path-specified "
#include < path-specified >

Both syntax forms have the effect that the #include directive is replaced by the entire content of the specified file. The difference between the two forms is the order of the paths the preprocessor looks for if the path is not fully specified. The following table shows the difference between the two forms of syntax.

You can arrange the definitions of macros and constants in an include file (also known as a header file) and then use the #include directive to add them to any source file.

Include files are also useful for combining external variable declarations and complex data types. Types can be defined and named only once in an include file created for this purpose.

path-specified is a file name, which may be preceded by a directory specification. The file name must point to an existing file. The syntax for specifying the path depends on the operating system on which the program is compiled.

” path-specified “

The preprocessor searches for include files in this order:

  1. In the same directory as the file that contains the #include statement.

  2. In the directories of the currently opened include files, in the reverse order in which they were opened. The search begins in the directory of the parent include file and continues upward through the directories of any grandparent include files.

  3. Along the path that’s specified by each /I compiler option.

  4. Along the paths that are specified by the INCLUDE environment variable.

< path-specified >

The preprocessor searches for include files in this order:

  1. Along the path that’s specified by each /I compiler option.

  2. When compiling occurs on the command line, along the paths that are specified by the INCLUDE environment variable.

This example shows file inclusion by using angle brackets:

  #include <stdio.h> 

The example adds the contents of the file named stdio.h to the source program. The angle brackets cause the preprocessor to search the directories that are specified by the INCLUDE environment variable for stdio.h, after it searches directories that are specified by the /I compiler option.

The next example shows file inclusion by using the quoted form:

  #include "defs.h" 

The example adds the contents of the file that’s specified by defs.h to the source program. The quotation marks mean that the preprocessor first searches the directory that contains the parent source file.

Nesting of include files can continue up to 10 levels. When processing of the nested #include is finished, the preprocessor continues to insert the enclosing parent include file into the original source file.

#Include directives

#ifndef _FILE_NAME_H_
#define _FILE_NAME_H_
 
/* code */
 
#endif // #ifndef _FILE_NAME_H_

System and custom header files are included using the `#include” directive preprocessor. It comes in three flavors:

  #include <file>

This option is used for header files. Search for a file with the filename in the list of directories that you specify, then in the standard list of system directories. You specify directories to search for header files with the I ‘command option. The -nostdinc option restricts the search in standard system directories; In this case, only the directories that you specify will be searched.

The parsing of this #include form is somewhat odd because the comment is not recognized in <...>. Therefore, in #include <x/*y>,/* does not start a comment, but the directive instructs to include a system header file named x/*y. Of course, a header file with that name is unlikely to exist on Unix, where shell wildcards are difficult to manipulate.

The arguments file cannot contain the > character. However, it can contain < personality.

  #include "file"

Use this option for your own program header files. First find the file with the filename in the current directory and then in the same directories that were used for the system header file. Current directory is the directory of the current input file. Tried it first as it is assumed to be the location of the files that the current input file belongs to. (If the ‘I’ option is used, special handling of the current directory will be limited.)

The arguments file cannot contain the characters ". If backslashes are encountered in the file, they are treated as normal text characters, not symbols. Inappropriate character escapes for C string constants are handled. Thus, #include "x\n\\y" only specifies filenames containing three backslashes. It is not clear why this behavior is useful, but the ANSI standard defines

How ‘#include’ works

The ‘#include’ directive tells the C preprocessor to scan the input file before continuing with the rest of the current file. The preprocessor output contains the generated output, followed by the output from the included file, followed by the output from the text after the #include directive. For example, given the header file and #header.h like this:


 char * test (); 
 

and a main program called program.c uses a header file, for example,

 int x; 
 #include "header.h" 
 
 main () 
 {
 printf (test ()); 
} 

the output generated by the C preprocessor for program.c as input will be

 int x; 
 char * test (); 
 
 main () 
 {
 printf (test ()); 
} 

Included files are not limited to macro declarations and definitions; This is just typical usage. Any segment of a C program can be included from another file. An include file may even contain the beginning of a statement that ends in the file it contains, or the end of a statement that begins in a including files. However, a comment, line, or character constant may not start in an included file, or end in an included from file.

A header file can start or end a syntax unit just like a function definition, but this can be confusing, so don’t do that.

The line following the #include directive is always treated as a separate line by the C preprocessor, even if the included file does not have a trailing newline character.

What it does is very simple - it looks through the source code one line at a time (unlike the regular C/C++ compiler that treats newlines as whitespace).

If a line starts with whitespace and then a ‘#’ sign then it treats this as a directive to do something (include some other file, define a macro, do compile-time conditionals, etc).

As it reads through the source file - it (at least conceptually) outputs a new source file with all of the ‘#’ directives removed - and with all of the included files expanded out, all of the #ifdef/#if/#else/#endif stuff processed out and with macro’s expanded as needed.

The resulting output file then goes off to the actual C compiler - which never sees a ‘#’ directive and compiles every single line of code regardless.

In practice, it’s a bit more complicated than that.

If this were literally true - then doing a #include and then writing a 4 line “Hello World” program with an error on line 3 would result in the main C compiler complaining of an error on line 587 instead of line 3 because it would be counting all of the lines inside the stdio.h file!

So in practice, more complicated things happen. The C preprocessor emits #FILE and #LINE directives that say which file and which line the source code originally came from - and the C compiler itself would recognize those directives and use them to keep count of where we are in the source code.

But, as I said, the days when the C preprocessor literally was a preprocessor that read one file and wrote another are long gone.

https://coliru.stacked-crooked.com/a/71c42200f19b9d9f

#include <stdio.h>  
#define PI 3.1415 
int main() 
{  
   printf("%f",PI);  
}  
g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

3.141500

The preprocessor defines four useful constants for us. Using these four constants can provide more information in the error message. They are:

__FILE__ File name

__LINE__ current line number

__TIME__ The time the file was compiled

__DATE__ The date the file was compiled

For example, we can use the following small examples to see the use of these constants. This function is designed to evaluate whether the input word is less than the specified minimum length; if it is less, an error message will be displayed. It looks like this:

//main.cpp
#include <iostream>
#include <string>
using namespace std;
 
int main()
{
	const string::size_type THRESHOLD = 3;
	string word;
	cin >> word;
	if (word.size() < THRESHOLD){
		cerr << "Error: " << __FILE__ << endl << "\tline " << __LINE__ << endl
			<< "\tComplied on " << __DATE__ << " at " << __TIME__ << endl
			<< "\tWord read was " << word << ": Length too short" << endl;
	}
	return 0;
}

g++ -std=c++20 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Error: main.cpp

	line 11

	Complied on Sep 10 2021 at 09:59:59

	Word read was : Length too short


C #define preprocessor

#define [identifier name] [value]

The source code of the C preprocessor handler,Run before compilingUsually with a symbol # At the beginning, there are three main aspects of C language preprocessing (third)

  1. Macro definition and macro replacement #define

“Macro” is borrowed from the concept of assembly language, in order to facilitate some definition and extension

Take #define Start, divided

(1) Macro definition of symbolic constants
(2) Macro definition with parameters

1.1 Macro definition of symbolic constants:#define identifier string

Note: The identifier is the name of the macro, which is used to identify the constant string, and the macro definition does not have a semicolon at the end.

Since the preprocessing is before compilation, the preprocessing does not do grammar checking and the macro definition does not allocate memory, the variable definition allocates memory

1.2 Macro definition with parameters and its replacement : #define identifier (parameter table) string

When macro substitution is performed on a macro definition with parameters, not only the macro identifier is replaced by a string, but also the parameter must be replaced.

example: Macro definition #define Func(x) (x*x), then Fun(a+B)

What will be replaced?

answer: Replaced with (a+Ba+B) is visible if you want to implement (a+B)(a+B), the correct macro definition should be: #define Func(r) ((r)*(r))

Therefore: in order to avoid errors when macro replacement, the macro parameters in the macro definition should be bracketed

Macro definitions can be nested: example:

#define ADD(x, y) x+y
int m = 3;
m + = m * ADD(m, m);
m = ?

Analysis:

m + = m* ADD(m, m);
m = m + m * m + m = 3+ 3*3 +3 = 15

1.3 The essence of macro definition is text replacement:

Points to note about macro definitions and macro replacement

The macro name is an uppercase (identifier); there can be no spaces between the macro name and the parameter brackets, and there is no semicolon at the end.

Macro substitution only replaces, does not check grammar, does not do calculations, does not solve expressions, Macro replacement in, Before compiling, Do not allocate memory, Function call is run after the program is compiled Carry out and allocate memory The function has only one return value, and the macro can try to have multiple values. Macro substitution makes the source program longer, function calls will not Macro replacement does not take up runtime, only compile time, function call takes up runtime

Note: Macro substitution should be used sparingly, in C++,Macro replacement implementation of the constant function byconst,enumInstead, the macro substitution with parameters is replaced by the template inline function.

  1. The file contains#include

    #include :< > Standard header file

    #include “a.h”: “ “ Custom header file

  2. Conditional compilation effect: Enables the same source program to generate different object code according to different compilation conditions (parameters), which is convenient for debugging and porting.

form:(Conditional compilation control statements have different forms)

#if / ifdef / ifndef
#elif
#else
#endif

File contains to be avoided Multiple Including, the following describes the use of conditional compilation statements to avoid multiple inclusions:

  1. to avoid name conflicts, preprocessor variables are often expressed in uppercase letters
  2. The preprocessor variable has two states: Defined and undefined

#define Indicate a name and define the name as a preprocessor variable #ifndef Check if the specified preprocessor variable is undefined, If the preprocessor variable is undefined, then all statements following it are processed until they appear #endif

Give a format example
#ifndef SALESITEM_H
#define SALESITEM_H
// Here is a class definition and related function definition
#endif

To ensure that the header file is only processed once in a given source file, first check #ifndef If it is processed for the first time, then #ifndef The following statement is executed until #endif, then, after it has been defined, it will be ignored after compiling.

Preprocessor Directives The preprocessor directives that C/C++ supports are: ■ #define, to create macros for use by the precompiler and the C or C++ compiler ■ #include, to read other source files for use by the precompiler ■ #if, to precompile and compile source text based on evaluation of a constant expression to 0 ■ #ifdef, to precompile and compile source text conditionally, depending on the existence of a defined constant ■ #ifndef, to exclude source text conditionally ■ #endif, to end an #if or #ifdef or #ifndef command ■ #else, to select an alternative body of source text to be precompiled and compiled, in case an #if or #ifdef or #ifndef condition is not satisfied ■ #elif, to select an alternative body of source text to be precompiled and compiled, depending on the value of a constant or a macro argument ■ #, to convert a preprocessor macro parameter to a string constant ■ ##, to merge two preprocessor tokens in a macro definition ■ #error, to produce a compile-time error message ■ #pragma, to pass implementation-dependent information to the C compiler ■ #line, to supply a line number for C compiler messages

A safer method is to use an #if 0 directive around the code you want to block out.

#if 0
/* #if 0 evaluates to false, so everything between here and the #endif are
 * removed by the preprocessor. */
int myUnusedFunction(void)
{
    int i = 5;
    return i;
}
#endif

A benefit with this is that when you want to go back and find the code, it’s much easier to do a search for “#if 0” than searching all your comments. Another very important benefit is that you can nest commenting out code with #if 0. This cannot be done with comments.

Error directive If the preprocessor encounters an #error directive, compilation is halted and the diagnostic message included is printed.

#define DEBUG
#ifdef DEBUG
#error "Debug Builds Not Supported"
#endif
int main(void) {
    return 0;
}

Possible output: $ gcc error.c error.c: error: #error “Debug Builds Not Supported”

How a Preprocessor works in C?

A preprocessor is system software (a computer program designed to run on computer hardware and application programs). It carries out high-level language preprocessing (HLL). Preprocessing is the first step in system language processing. High-level language in machine language or absolute machine code (i.e. in the machine-understandable form).

processing

A preprocessor performs three main tasks in HLL code:

Remove comments: Removes all comments. A comment is only written to help people understand the code. Hence it is obvious that they are of no use to a machine. Therefore, the preprocessor removes them all, as they are not required and will not be executed when executing.

File integration:

Including all library files that our program needs. In HLL we write #include, which is a directive for the preprocessor that tells it to include the contents of the specified library file. For example, #include will tell the preprocessor to include all content in the library file stdio.h.

This can also be written in double quotation marks - #include “stdio.h”

Note: If the file name is in angle brackets, the file will be searched for in the standard compiler include paths. If the file name is enclosed in double quotation marks, the search path is expanded to include the current source directory.

Macro Enhancement:

Macros can be called as small functions that are not that expensive to process, so if we need to write a function (with a small definition) that needs to be called recursively (over and over) we should prefer a macro . via a function.

prelist

Pre-processing

This is the first phase through which source code is passed. This phase include:

Removal of Comments
Expansion of Macros
Expansion of the included files.
Conditional compilation

The preprocessed output is stored in the filename.i. Let’s see what’s inside filename.i: using $vi filename.i In the above output, source file is filled with lots and lots of info, but at the end our code is preserved.

Preprocessor Directives:

What are preprocessor in C?

Suppose we have a “.c” file named “main.c” with a “.c” extension. This file is then processed by the preprocessors and in the next step an object file with the extension “.obj” is compiled and generated. Then the “.obj” file is linked with the standard library functions to create a file with the extension “.exe” and then executed.

How does a preprocessor work in C?

Below are the steps involved while preprocessing:-

  1. Filtering out comments:– In C, comments are used for better understanding of different steps which are included in the program. Compiler filters out the comments during processing.

  2. File Inclusion:– It tells the compiler to include certain header files so that certain functions can be performed. In 2 ways, you can do it:-

    #include #include ”filename.h”

  3. Macro Expansion:– In some situations, you will need to use some blocks of code in a recursive function. In 2 ways, you can do it:-

  4. Object-like macros:– Does not take parameters.

  5. Function-like macros:– Capable of taking parameters.

What are C preprocessor directives?

Instructs the compiler to preprocess the source code before compiling it. Preprocessor directives are mainly used as commands. In “C”, all preprocessor directives begin with a “pound / diamond (#)” symbol. Preprocessor directives anywhere in the program, but it is best to use preprocessor directives at the beginning of the program.

Types of Preprocessor in C

There are 4 main types of preprocessor directives:-

Macros
File Inclusion
Conditional Compilation
Other directives

Macros in C

Programmers use macros to execute snippets of code within the macro. A programmer gives the macro a name. And when the compiler finds the specified name, the compiler replaces the name with the code snippet that is in the macro. The “#define” directive is used to define a macro.

#include <stdio.h>
#define LIMIT 4 // defining macro!
int main()
{
for (int a = 0; a < LIMIT; a++) {
printf("%d \n",a);
}
return 0;
}

In the above example, the compiler replaces LIMIT with 5. LIMIT is a macro template and 5 is macro expansion.

Macros with arguments

We can also pass arguments to the macros. Macros with arguments work similarly as functions.

#include <stdio.h>
#define AREA(s) (s * s) // macro with argument
int main()
{
int s1 = 10, area_of_square;
area_of_square = AREA(s1);
printf("TechVidvan Tutorial: Macros with arguments!\n");
printf("Area of square is: %d", area_of_square);
return 0;
}

In the above example, the compiler finds the name of the macro (AREA(s)) and replaces it with the statement (s * s).

Function like Macros in C

Define macros that work similarly like functions.

#include <stdio.h>
#define MIN(a,c) ((a) > (c) ? (c) : (a))
int main(void) {
   printf("Between 30 and 70, minimum number is: %d\n", MIN(10, 20));  
   return 0;
}

File Inclusion

This preprocessor directive tells the compiler to include a file in the program code. A user can include two types of file:-

Header or Standard files

These files contain functions like printf(), scanf(). In a single word, it contains predefined functions. Different header files contain different functions. Like, string file contains string handling functions and iostream file contains input/output functions.

User defined files

A programmer can define his/her own header file to divide a complex code into small blocks of code.

Conditional Compilation in C

The main purpose of this preprocessor directive is to compile specific parts of the code or skip the compilation of specific parts of the code based upon some conditions.

How to use conditional compilation directives?

With the help of two preprocessing methods, you can implement the conditional compilation directive.

ifdef
endif

 
#ifdef macro_name
		statement1;
		statement2;
		statement3;
	.
	.
	.
		statementN;
#endif

If the macro name is defined, then it will normally execute the block of statements. And if it is not defined, then the compiler will skip the block of statements.

Apart from #ifdef and #endif directives, there are some other directives such as #if, #elif, #else and #defined directives.

#if, #elif, #else directive in C

You can also use #else directive with #if directive. If the given expression results in a non zero value, then the codes of conditional are included in the program.

#if expression
// conditional statements if expression is not zero
#else
// conditional statements if expression is zero
#endif

You can also use nested conditional in your program with the help of #elif directive.

#if expression1
// conditional statements if expression1 is not zero
#elif expression2
// conditional statements if expression1 is not zero
#else
// conditional statements if all expressions is zero
#endif

#defined directive in C

Mainly used to check whether a certain macro is defined or not. You can use #if directive with #defined directive.

#if defined LENGTH || WIDTH >= 10
  	// body contains code

Uses of C Conditional Compilation:-

Compile the same source file in different programs.
Depending on the OS, you can use different code.

Other directives in C

There are also two not so used directives available in C.

If you use the above statement then it will undefine the existing macro LIMIT.

#include <stdio.h>
void f1();
void f2();
#pragma startup f1
#pragma exit f2
void f1()
{
  printf("Executing f1() function!\n");
}
 
void f2()
{
  printf("Executing f2() function!\n");
}
 
int main()
{
  void f1();
  void f2();
  printf("TechVidvan Tutorial: pragma startup and pragma exit!\n\n");
  printf("Executing main() function!\n");
 
  return 0;
}
TechVidvan Tutorial: pragma startup and pragma exit!

Executing f1() function!
Executing main function!
Executing f2() function!

But if you run this in GCC compiler, it will give output like this:-

TechVidvan Tutorial: pragma startup and pragma exit!

Executing main function!

Because GCC compiler does not support #pragma startup or #pragma exit.

  1. #pragma warn directive:- Mainly used to hide warning messages that are displayed while compilation.
  2. #pragma warn -rvl:- Mainly used to hide the warnings when a function does not return a value as it is supposed to.
  3. #pragma warn -par:- Mainly used to hide the warnings when a function does not use the parameters which are passed to it.
  4. #pragma warn -rch:- Mainly used to hide the warnings when a code is unreachable.

Preprocessor Operators in C

There are various operators that help to create macros.

  1. Macro Continuation(/) operator in C

Mainly used to continue a macro which is too long to a single line.

Preprocessor Operators in C

There are various operators that help to create macros.

  1. Macro Continuation(/) operator in C

Mainly used to continue a macro which is too long to a single line.

#define  message_of_the_day(i, j)  \
   	printf(#i " and " #j ": TechVidvan Tutorial: Macro Continuation!")
  1. Stringize Operator(#) in C

The main purpose of this operator is to convert a macro parameter into a string.

#include <stdio.h>
#define statement(i)  \
  printf(#i ": Macro Stringize!\n")
 
int main(void) {
   statement(TechVidvan Tutorial);
   return 0;
}

TechVidvan Tutorial: Macro Stringize!
  1. Defined() Operator in C

Mainly used to determine if an identifier is defined. If it is defined, then the value will be non-zero.

#include <stdio.h>
#if !defined (MSG)
   #define MSG "Macro Defined() operator!"
#endif
int main(void) {
   printf("TechVidvan Tutorial: %s\n", MSG);  
   return 0;
}
TechVidvan Tutorial: Macro Defined() operator!
  1. Token Pasting(##) Operator in C

Mainly used to combine two arguments.

#include <stdio.h>
#define tokenpaster(num) printf ("token" #num " = %d", token##num)
int main(void) {
int token1 = 21;
printf("TechVidvan Tutorial: Token Pasting(##) operator\n\n");
   tokenpaster(1);
   return 0;
}
TechVidvan Tutorial: Token Pasting(##) operator

token1 = 21

pre processing

There are 4 main types of preprocessor directives in C. Preprocessor allows you to define macros that transform your program before it is compiled.

Programmers use macros to execute pieces of code inside the macro. The #define directive is used to define a macro. ‘Pre’ means before and ‘processor’ means making something.

Sources:



Paylaş:



En Yeni İçerikler