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.141516
Considering preprocessing for main the value of pi should be 3.141516 and outside main 3.14. This is incorrect but please explain why.
6 Answers 6
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;
.
-
1"or (as in this case) the macro is re-defined with another
#define
statement." In fact, the second#define
without a preceding#undef
makes the program ill-formed.James McNellis– James McNellis2011年06月16日 23:06:28 +00:00Commented Jun 16, 2011 at 23:06 -
2Note that
const
does not create a constant usable, for instance, in switch labels: it creates a read-only object. Example at ideone.com/f3aONpmg– pmg2011年06月16日 23:15:11 +00:00Commented Jun 16, 2011 at 23:15 -
This is a good answer to the question raised but strictly speaking the #define does not have scope over the entire file. Specifically it would not modify pi in a string such as "the value of pi is 3" This would not become "the value of 3.14 is 3"Allen Edwards– Allen Edwards2024年07月09日 02:35:23 +00:00Commented Jul 9, 2024 at 2:35
-
No, reaching the end of file does not cause macros to be undefined (the standard library wouldn't be able to provide any macros if this were the case). Macros stay defined until the corresponding
#undef
or the end of the entire translation unit.Toby Speight– Toby Speight2024年10月14日 07:43:50 +00:00Commented Oct 14, 2024 at 7:43
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.
-
1"The scope of a
#define
is from the occurrence, to the end of the file" - or if it is#undef
'ed before EOF is reached.Remy Lebeau– Remy Lebeau2020年09月23日 03:00:35 +00:00Commented Sep 23, 2020 at 3:00
When you have preprocessor question:
gcc -E foo.c> foo.i; vim foo.i
-
Can you elaborate?Peter Mortensen– Peter Mortensen2024年10月13日 23:04:45 +00:00Commented Oct 13, 2024 at 23:04
-
According to
gcc --help
, it is:Preprocess only; do not compile, assemble or link
. That means that all#define
clauses will be expanded and substituted in the code, but the code itself will not be compiled. In the code from the question, you would see literal3.14
and3.141516
instead ofpi
.whiskeyo– whiskeyo2024年10月14日 06:57:37 +00:00Commented Oct 14, 2024 at 6:57
Here is what it roughly looks like after the preprocessor is 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 much of the code 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.
The preprocessor doesn't have any concept of "scope"—it manipulates the text of the program, without any idea of what the text is.
A symbol is defined from its definition until the end of the compilation unit (a source file and the files it includes).
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?).
#define
a macro with the same name as another macro that is currently defined unless their definitions are the same. So, the second#define pi
makes the program ill-formed. You need to#undef pi
first.