问题
Consider following program:
#include <cstdio>
int main()
{
int printf=9;
std::printf("%d",printf);
}
Is it fine to use built in function name as an identifier in variable declaration? Is this well defined program? I mean is behaviour of above program well defined? I am curious to know whether the C++ standard allows to use standard function names as identifiers of variables
回答1:
It's well-formed because neither std::printf
nor ::printf
(which may also have been declared by <cstdio>
!) are declared in the same scope as your integer, which therefore takes automatic precedence for the duration of the block.
[C++14: 3.3.1/1]:
[..] To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative region is excluded from the scope of the declaration in the outer (containing) declarative region.
For example, you generally wouldn't be able to do this at namespace scope.
It's well-defined because the names of entities in the standard library are not inherently reserved names:
[C++14: 2.11/3]:
In addition, some identifiers are reserved for use by C++ implementations and standard libraries (17.6.4.3.2) and shall not be used otherwise; no diagnostic is required.
[C++14: 17.6.4.3.2/1]:
Certain sets of names and function signatures are always reserved to the implementation:
- Each name that contains a double underscore
_ _
or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.- Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
回答2:
Yes, this is well defined behavior. You are creating an int named printf, and there is nothing currently named printf in your scope. There is something named printf in the standard scope and possibly in the global scope, but the int printf defined in local scope automatically takes precedence.
回答3:
It is technically allowed to do this. There are names that are reserved in the global namespace, but inside a function, your variable name won't be visible outside the function anyway, so not a problem.
It is a terrible idea to use this.
And beware that there CAN BE problems with this approach. For example:
#define NULL 0
int main()
{
int NULL = 42;
printf("%d", NULL);
}
is not allowed, since NULL
is a macro, and not a scoped identifier.
Edit: I would add that printf
is not a "built in function". It is a "C standard library function". A bultin function is something like __builtin_sin
, which the compiler "knows about" so that it can be optimised. Note that builtin functions typically use "reserved names", to avoid colliding with existing library and user-defined names at all times.
回答4:
Relative to the identifiers in the standard libraries then the C++ Standard states only the following restruction for identifiers
3 In addition, some identifiers are reserved for use by C++ implementations and standard libraries (17.6.4.3.2) and shall not be used otherwise; no diagnostic is required.
And (17.6.4.3.2 Global names)
1 Certain sets of names and function signatures are always reserved to the implementation:
— Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
So you may use identifiers that coincide with standard function names.
On the other hand this can confuse readers of the code and lead to ambiguity. Take into account that the Standard allows compilers to place standard C function names in the global namespace.
回答5:
It is OK to do so. Because the variable int printf
you defined do not belong to the namespace std
as printf
, which is defined in cstdio
. So there is actually no conflict in names of your program.
However, if you declare
using namespace std;
before your program, and no std::
used later in your program, then it'll cause problems if you're not careful. Generally, when there is name conflicts, compiler will use the name defined in smallest scope. So if you have program like:
#include<cstdio>
using namespace std;
int main()
{
int printf = 42;
printf("%d", printf);
}
The compiler will return
error: ‘printf’ cannot be used as a function
This is because in this program, printf
is defined as a int
in function scope, and as a function int printf( const char* format, ... )
in global scope. Since function scope is smaller than global scope, in function int main()
, printf
is intepreted as int
rather than function. int
is not callable, hence the error message.
来源:https://stackoverflow.com/questions/33856187/is-it-valid-to-use-standard-library-function-name-as-identifier-in-c