Source Code: Biggest of 3 Numbers using Macros: C Program
#include<stdio.h>
#define BIGGEST(x, y, z) ( (x > y && x > z) ? x : ( y > z) ? y : z )
int main()
{
int a, b, c;
printf("Enter 3 integer numbers\n");
scanf("%d%d%d", &a, &b, &c);
printf("Biggest of 3 numbers is %d\n", BIGGEST(a, b, c));
return 0;
}
Output: Enter 3 integer numbers 20 50 60 Biggest of 3 numbers is 60
Here we’re writing logic inside macro expansion. Wherever macro template is found in our source code, preprocessor replaces that macro template with macro expansion and the compiler compiles the code like normal source code.
Nested Ternary / Conditional Operator
Here we are using nested conditional operator. First we check if value of a is greater b and c, if true, value of a will be returned orelse we check if b is greater than c, if true, value of b will be returned orelse value of c will be returned.
In this video lets see how we can have multiple line of code inside macro expansion, by using preprocessor operator – macro continuation( \ ).
Where Is It Used?
While you’re writing complex logic inside macro expansion, you’ll need to break the line and write code in next line. In such cases macro continuation operator is very helpful. And the code looks much cleaner and clearer.
Video Tutorial: Macro Continuation (\) Preprocessor Operator: C Program
#include<stdio.h>
#define SQUR(x) \
printf("Square of %d is %d\n", x, (x * x));
int main()
{
SQUR(5);
return 0;
}
Output: Square of 5 is 25
Here we are writing the macro expansion in the next line, so we are making use of macro continuation preprocessor operator (\).
Source Code: Macro Continuation (\) Preprocessor Operator: C Program
#include<stdio.h>
#define COMPANY(x) switch(x) { \
case 1: printf("1. Oracle\n"); break; \
case 2: printf("2. IBM\n"); break; \
case 3: printf("3. Ripple\n"); break; \
default: printf("default. Banks\n"); \
}
int main()
{
COMPANY(3);
COMPANY(2);
COMPANY(50);
return 0;
}
Output: 3. Ripple 2. IBM default. Banks
Here we’ve multiple lines of code inside macro expansion. So at the end of each line we’ve written macro continuation symbol ( \ – backslash). Wherever you write the macro template, preprocessor will replace it with the macro expansion before execution.
In today’s video tutorial lets look at couple of predefined Macros in C programming Language.
Uses of Predefined Macros
It’s very useful for developers while debugging the code, in a large project. Using these predefined macros you could write less code and integrate more features into the program. For example, to get current system date/time and timestamp you need not write lengthy code, just write the predefined macro and use the output in your source code.
Video Tutorial: Built-in Preprocessor Directive: C Program
Output: File: C:\Technotip\main.c Date: Jul 18 2020 Time: 14:11:52 Timestamp: Sat Jul 18 14:11:48 2020 Line: 9 ANSI: 1 Function Name: main Pretty Function name: main
Slno
Macro Name
Description
1
__FILE__
The name(along with full path) of the current file, as a string literal.
2
__DATE__
Current System date, as a string literal.
3
__TIME__
Current System time, as a string literal.
4
__TIMESTAMP__
Current System date and time(non-standard), as a string literal.
5
__LINE__
Current line in the source code file where __LINE__ is written, as numeric literal.
6
__STDC__
its value is 1, when the compiler compiles with the ANSI standard.
7
__func__
function name in which the __func__ resides.
8
__PRETTY_FUNCTION__
function name in which the __PRETTY_FUNCTION__ resides.
__PRETTY_FUNCTION__ and __func__ returns same value, but not all compilers support both. Sometimes its compiler specific.
Note: We do not include or import any file to make these Macros work. It looks like all these are working out-of-the box, so sometimes these are called as Magic Constants.
Output: We’re inside init method We’re inside main method We’re inside end method
We could even use __attribute__((constructor)) and __attribute__((destructor)) in function definition, as shown in above source code.
Source Code: Suppressing warnings using #pragma Directive: C Program
#include<stdio.h>
#pragma warn -rvl /* No Return Value */#pragma warn -par /* Parameter Not Used */#pragma warn -rch /* Unreachable Code */
int main()
{
int count = 1;
printf("%d\n", count);
return 0;
count++;
}
int total()
{
printf("Sum of a and b is c\n");
}
void end(int x)
{
printf("We're inside end method\n");
}
Output: 1
Here function total has a return type of integer, but it doesn’t return any value from inside, so it must throw “no return value” warning. But that warning is suppressed by #pragma warn -rvl .
Function end takes a integer argument, but the value is nowhere used inside the function definition. Compiler should throw “Parameter Not Used” warning, but it’s suppressed by #pragma warn -par.
Inside main method, there is count++ after return. This code is never executed. So the compiler should throw “Unreachable Code” warning, which is suppressed by #pragma warn -rch.
Note: -(minus or subtraction) symbol before rvl, par and rch means compiler removes the warning. + sign indicated the warning will be shown in the editor after compilation of the program.
Also note that,
#pragma warn -rvl /* No Return Value */#pragma warn -par /* Parameter Not Used */#pragma warn -rch /* Unreachable Code */
doesn’t work on GCC compiler.
Important Note: The functions init() and end() should not receive any arguments and should not return any value, if we want to handle their invocation via #pragma.
#undef removes or undefines a macro name which is previously created or defined using #define directive.
Syntax
#undefMACRO_NAME
Note: If a Macro template is associated with a Macro expansion, you need not mention the macro expansion to undefine the macro. You simple undefine using this syntax: #undef MACRO_NAME
Video Tutorial: #undef Preprocessor Directive: C Program
#include<stdio.h>
#define iOS
#undef iOS
int main()
{
#if defined(iOS)
printf("I Love Apple Devices\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: Macro iOS has been undefined
In above source code we’re undefining the Macro iOS immediately after defining it. So defined(iOS) returns false or 0. So code inside #else block gets compiled and executed.
#include<stdio.h>
#define iOS
int main()
{
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("Gift me a latest iPhone!\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: I Love Apple Devices Gift me a latest iPhone!
Here Macro iOS is defined, so defined(iOS) returns true. That’s why block of code inside #if directive gets compiled and executed.
#include<stdio.h>
#define iOS
int main()
{
#undef iOS
#if defined(iOS)
printf("I Love Apple Devices\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: Macro iOS has been undefined
Even though #define iOS is defined at global level you can undefine it inside main() method.
Note:defined() is a preprocessor operator which returns true if the passed macro name is defined orelse returns false or zero if its not defined.
Instead of defined() preprocessor operator you could even use #ifdef or #ifndef to check if the Macro template or Macro name is defined or not defined.
#include<stdio.h>
#define iOS
int main()
{
int flag = 1;
do
{
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("This displays all your iPhone Device Details\n");
#else
printf("I'm inside do while block.\n");
#endif // defined
printf("Enter your choice? (0/1)\n");
scanf("%d", &flag);
}while(flag);
#undef iOS
#if defined(iOS)
printf("I Love Apple Devices\n");
printf("This displays all your iPhone Device Details\n");
#else
printf("Macro iOS has been undefined\n");
#endif // defined
return 0;
}
Output: I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 1 I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 1 I Love Apple Devices This displays all your iPhone Device Details Enter your choice? (0/1) 0 Macro iOS has been undefined
In above program we are defining iOS macro globally. Inside main method we use do while loop and keep executing #if #else #endif directives. Since iOS is defined, the block of code inside #if gets executed each time. Once user enters 0 as input, the control exits do while loop execution. Next it encounters #undef iOS, so defined(iOS) now returns false or 0, hence code inside #else directive gets executed.