This question already has answers here:
Scope of #define preprocessor in C
(6 answers)
Closed 8 years ago.
Here are two pieces of C code, but I don't understand how they work:
Program 1 :
#include<stdio.h>
#define s 10
fun() {
#undef s
#define s 20
}
int main(){
printf("%d\n",s);
fun();
printf("%d\n",s);
return 0;
}
Output: 20
20
Program 2:
#include<stdio.h>
#define s 10
int main(){
printf("%d\n",s);
fun();
printf("%d\n",s);
return 0;
}
fun() {
#undef s
#define s 20
}
output: 10
10
What I know is preprocessor works before starting of main() and replaces all of its variables.
Here fun() is called after one printf(), so how are both program are outputting different values by changing the position of fun()?
Macro will be replaced in compile time itself. so code will be like this after preprocessing,
Case 1:
#include<stdio.h>
fun() {
}
int main(){
printf("%d\n", 20);//latest definition of s will be considered.
fun();
printf("%d\n",20);
return 0;
}
Case 2:
#include<stdio.h>
int main(){
printf("%d\n",10); //replaced with 10 only, because in this instance, there is no change in s
fun();
printf("%d\n",10);
return 0;
}
fun() {
//#undef s
//#define s 20 //no use in ur code.
}
fun_extra() { //Added for demo
printf("%d\n",s);//will be replaced by 20.
}
The preprocessor doesn't care about scope. It just goes through the file line by line, in order from top to bottom, and makes textual replacements. If something is #defined or #undefined, it takes effect from that line until the bottom of the file (or another preprocessor statement overrides it).
Preprocessor statements are not executable. They are... well, preprocessed. This means that the compiler will perform an initial, single pass and resolve all preprocessing definitions. If a preprocessing definition is located inside a C control structure, it will be executed regardless of the meaning of the C control structure. In other words, from the point of view of the preprocessor there is no C code. Just text (and other preprocessor statements).
In your case, in this first pass:
#include<stdio.h> // File stdio.h is included/copied
#define s 10 // Preprocessor symbol s is defined as 10
fun() { // Copied literally
#undef s // Preprocessor symbol s is undefined
#define s 20 // Preprocessor symbol s is defined as 20
} // Copied literally
int main(){ // Copied literally
printf("%d\n",s); // Copied with s substituted, ie. printf("%d\n",20);
fun(); // Copied literally
printf("%d\n",s); // Copied with s substituted, ie. printf("%d\n",20);
return 0; // Copied literally
} // Copied literally
So, the input that really gets compiled is:
// Empty line originally corresponding to #include
// Empty line originally corresponding to #define
fun() {
// Empty line originally corresponding to #undef
// Empty line originally corresponding to #define
}
int main(){
printf("%d\n",20);
fun();
printf("%d\n",20);
return 0;
}
In particular, note that the fun function does not contain any C instruction. Before pre-processing it did contain 2 pre-processing instructions, but:
They disappeared after pro-processing
They never really belonged to a function fun because at that point there was no function fun or any other C code. Just text and preprocessor statements.
This work is usually done silently and internally by C compilers. However, many of them have options to save the pre-processed source files. You should obtain a result like the above (except that #include<stdio.h> would expand into many blank lines, and some C code, which here I sinthesized as a single empty line).
The second case is left as an exercise to the OP.
Related
#include <stdio.h>
#define MYNUMBER 123
int main()
{
printf("%d", MYNUMBER456);
}
Above code doesn't work because MYNUMBER and MYNUMBER456 are different token.
#include <stdio.h>
#define SECOND(a, b) printf(#a #b);
#define FIRST SECOND
int main()
{
FIRST(hello, world!)
}
But this one works well. My thought is FIRST and FIRST(hello, world!) are different so it should not work. What am I missing?
You can see the macro expansion by using the -E option (cc -E main.c), though you will see a lot of other stuff inserted because of your #include <stdio.h>, and without it you will probable see some default stuff inserted, in your example the main function becomes
int main()
{
printf("hello" "world!");
}
This is because you have defined FIRST to be the same as SECOND which takes two arguments and makes them strings and since there is no comma between them they get concatenated into a single string, macros are just string substitution, in C the preprocessing is traditionally handled by a seperate executable to the compiler and is not as sophisticated as a compiler, so the type matching you would expect in most languages doesn't apply to the preprocessor.
you are correct MYNUMBER and MYNUMBER456 are different and the pre-compiler wont know how to work with MYNUMBER456
however, when you defined FIRST as SECOND , the precompiler would expand FIRST by SECOND and then you actually have SECOND with 2 parameters so it it working
I wrote the following program and surprising it shows a compilation error that
'X' undeclared in exapansion of macro.
The code in c is:
#include<stdio.h>
#define X (4+Y)
#define Y (X+3)
int main()
{
printf("ds", "ds");
printf("%d\n", 4*X+2);
return 0;
}
I accept that this results in a kind of infinite macro replacement, but if that was an error, that should have been a run time error(truly speaking no error at all). Am I correct? If not, please correct me and explain me where I am getting it wrong?
EDIT: I am surprised that the following code however works perfectly:
#include<stdio.h>
#define X (4+Y)
#define Y 4
int main()
{
printf("ds", "ds");
printf("%d\n", 4*X+2);
return 0;
}
The C preprocessor does not expand a macro while that macro is being expanded (including indirectly through another macro). So in the expansion of Y inside the expansion of X, the preprocessor leaves X as is, and thus you get an undefined variable error.
Not only does this prevent infinite expansion loops, it also provides a useful feature. Suppose, for example, that you want to write a macro which "wraps" an existing function:
#define my_function(x, y) do { \
fputs("Calling my_function\n", stderr); \
my_function(x, y); \
while(0);
The fact that my_function is not expanded inside its own expansion makes it possible to wrap the function with a macro with the same name, thereby avoiding source modifications.
For any passing language lawyers, the standard specifies (§6.10.3.4/2):
If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.
Creating .I file of your code in main.c file using gcc -E -o main.I main.c then we get a file which contains as below
int main()
{
printf("ds", "ds");
printf("%d\n", 4*(4+(X+3))+2);
return 0;
}
Hence macros just replaces the value. So in the expansion of Y inside the expansion of X, the preprocessor leaves X as is.
Hence as X is undefined error occurs.
I have this code but not able to understand the output. Can someone help out to know the behaviour
#include<stdio.h>
int main(){
int a =1;
#if(a==0)
printf("equal");
#else if
printf("unequal");
#endif
return -1;
}
Output comes out to be equal. Strange for me.
Also if i change the if condition to a==2, the output comes unequal
If i try to print value of 'a' inside 'if' block something like
#if(a==0)
printf("value of a: %d",a);
output comes out to be value of a: 1
Please some one explain the output.
The a in the preprocessor directive refers to preprocessor definitions, not variables in your program. Since a is not #defined, its value is effectively 0 for the purposes of #if.
The preprocessor directives (the lines starting with #) are dealt with at compile time, not at runtime. The a in that #if is not the same as the a variable you declared. The preprocessor just replaces it with 0, since there is no #define a statement anywhere. The variable a is unused in your program. If you do use it, like in the printf statement you show, it will get printed as expected - a value of 1 that you assigned to it.
#include<stdio.h>
int main(){
int a =1;
#if(a==0)
printf("equal");
#else if
printf("unequal");
#endif
return -1;
}
which you pass to the compiler will first go through the preprocessor whose output is then sent as an input to the compiler; the preprocessor will send
#include<stdio.h>
int main(){
int a =1;
printf("equal");
return -1;
}
to the compiler, which is the reason you see equal always. The reason is since a as a macro is undefined, the first condition is true, there by leading to only passing that statement on to the compiler. If you try adding #define a 1 next to the include directive, then you'll always see unequal as an output; but these changes affect only the compile time macro a and not the runtime variable a (both are entirely different).
All this because preprocessor is concerned only with compile-time constructs. What you really need may be
#include<stdio.h>
int main(){
int a =1;
if(a == 0)
printf("equal");
else
printf("unequal");
return 0;
}
Aside: Return 0 when you're program is successful, returning negative values from main usually means some error state termination of your program.
How to write C program without using Main...!
When I'm learning how to write ASM file by for a simple C file [of length 3 lines], I got this doubt.
I assembly file I used preamble and post ambles, at function.
There is a great article and creating the smalest possible elf binary here. It has a lot of info of what is required to have something runnable by the os.
This is logical trick. Those who are unaware of it, can learn this trick.
#include<stdio.h>
#include<conio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)
void begin()
{
clrscr();
printf("\nHello !!! Kaushal Patel.");
getch();
}
Explanation :
The
pre-processor directive #define with arguments is used to give an impression
that the program runs without main(). But in reality it runs with a
hidden main().
The ‘##‘
operator is called the token pasting or token merging operator. That is
how, I can merge two or more characters with it.
#define decode(s,t,u,m,p,e,d) m##s##u##t
The macro
decode(s,t,u,m,p,e,d) is being expanded as “msut” (The ## operator
merges m,s,u & t into msut). The logic is when I pass
(s,t,u,m,p,e,d) as argument it merges the 4th,1st,3rd & the 2nd
characters.
#define begin decode(a,n,i,m,a,t,e)
Here the
pre-processor replaces the macro “begin” with the expansion
decode(a,n,i,m,a,t,e). According to the macro definition in the previous
line the argument must be expanded so that the 4th, 1st, 3rd & the
2nd characters must be merged. In the argument (a,n,i,m,a,t,e)
4th,1st,3rd & the 2nd characters are ‘m’,’a’,’i’ & ‘n’.
So the third line “void begin” is replaced by “void main” by the pre-processor before the program is passed on for the compiler.
Source :
http://ctechnotips.blogspot.in/2012/04/writing-c-c-program-without-main.html
Here is your answer:->
#include <stdio.h>
extern void _exit(register int);
int _start(){
printf(“Hello World\n”);
_exit(0);
}
The scope of #define is till the end of the file. But where does it start from.
Basically I tried the following code.
#include<stdio.h>
#include<stdlib.h>
#define pi 3.14
void fun();
int main()
{
printf("%f \n",pi);
#define pi 3.141516
fun();
return 0;
}
void fun(){
printf("%f \n",pi);}
The output of the above program comes out to be
3.140000
3.141416
Considering preprocessing for main the value of pi should be 3.141516
and outside main 3.14. This is incorrect but please explain why.
The C preprocessor runs through the file top-to-bottom and treats #define statements like a glorified copy-and-paste operation. Once it encounters the line #define pi 3.14, it starts replacing every instance of the word pi with 3.14. The pre-processor does not process (or even notice) C-language scoping mechanisms like parenthesis and curly braces. Once it sees a #define, that definition is in effect until either the end of the file is reached, the macro is un-defined with #undef, or (as in this case) the macro is re-defined with another #define statement.
If you are wanting constants that obey the C scoping rules, I suggest using something more on the lines of const float pi = 3.14;.
The scope of a #define is from the occurrence, to the end of the file (or a corresponding #undef), regardless of any intervening C scopes.
When you have preprocessor question:
gcc -E foo.c > foo.i; vim foo.i
Preprocessor has no concept of "scope" -- it manipulates the text of the program, without any idea of what the text is
Symbol is defined from its definition until the end of the compilation unit (a source file and and files it includes)
Here is what roughly looks like after the preprocessor done with your file:
void fun();
int main()
{
printf("%f \n",3.14);
fun();
return 0;
}
void fun(){
printf("%f \n",3.141516);}
These are the lines that go to the compiler for compilation(I discarded many of the codes for the sake of clarity, only kept what you coded). As the preprocessor replaces the #define directive with the text/value you provided thus you don't see the #define directives anymore after preprocessing. So it is clear what is going to be printed on the console/terminal.
As far as I know, the preprocessor uses #define statements in the order that it encounters them. In that case, your first printf statement correctly prints 3.14 and the second 3.141516 (is there a typo in the output from your program?).