Reputation:
# include <stdio.h>
# define scanf "%s Hello World"
int main (void)
{
printf(scanf, scanf);
getchar();
return 0;
}
In the above code snippet, before the code is executed, the macro expansion phase takes place. In this, each occurrence of 'scanf' is replaced by "%s Hello World"
.
Hence printf(scanf,scanf)
will become
printf(“%s Hello World” , “%s Hello World”)
.
The final output will be :
%s Hello World Hello World
Now, no problems were encountered in this program because we did not use the scanf function here.
However, if we use the scanf function for some purpose
# include <stdio.h>
# define scanf "%s Hello World"
int main(void)
{
int x;
printf(scanf, scanf);
scanf("%d",&x);
getchar();
return 0;
}
We encounter an error :
main.c: In function ‘main’:
main.c:2:17: error: called object is not a function or function pointer
# define scanf "%s Hello World"
^
main.c:7:4: note: in expansion of macro ‘scanf’
scanf("%d",&x);
^~~~~
Why does then C allow us to name macros after library functions like Scanf in the first place ?
Upvotes: 2
Views: 490
Reputation: 223264
C 2018 7.1.3 1 says:
… Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
scanf
is an identifier with file scope listed in a following subclause (7.21), and you include its header, , so it is reserved for use as a macro name.
7.1.3 2 says:
… If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.
Combined, these rules say that, if you define scanf
as a macro name and include <stdio.h>
, the C standard does not impose any requirements on what happens—it is not specified to be an error in your program, nor is the compiler required to reject your program as incorrect. The compiler is also not required not to reject your program.
There is an alternative which avoids this problem: You can omit #include <stdio.h>
and instead declare printf
(and any other functions from <stdio.h>
that you use) yourself. The C standard explicits allows this, and then you can freely define a macro for scanf
.
This is typical of much of the C standard: It does not prevent you from doing things that can cause problems. In particular, it does not require the compiler warn you about it. There are at least three reasons (good or bad) the C standard is designed this way:
Upvotes: 5