What should happened if we use predefined variable __func__ outside a function in C (C99 / C11) and C++?
#include <stdio.h>
const char* str = __func__;
int main(void)
{
printf("%s", str);
return 0;
}
gcc 4.7.2 only give a warning (with -Wall -W -pedantic enabled) and prints nothing.
Standard doesn't say anything about it explicitly:
ISO/IEC 14882:2011
8.4.1 In general [dcl.fct.def.general]
8 The function-local predefined variable __func__ is defined as if a
definition of the form static const char __func__[] = "function-name";
had been provided, where function-name is an implementation-defined
string. It is unspecified whether such a variable has an address
distinct from that of any other object in the program.
ISO/IEC 9899:2011
6.4.2.2 Predefined identifiers
1 The identifier __func__ shall be implicitly declared by the translator as if, immediately
following the opening brace of each function definition, the
declaration static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing
function.
UB? Error? Or something else?
Standard doesn't say anything about it explicitly
This means undefined behavior.
From the C Standard (emphasis mine):
(C99, 4.p2) "If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside of a constraint is violated, the behavior is undefined. Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior. There is no difference in emphasis among these three; they all describe ‘‘behavior that is undefined’’."
(Promoted from an earlier comment)
__func__ is in the reserved namespace, so the implementation is allowed to use it at namespace scope for any purpose, i.e. the implementation is not required to diagnose a (mis)use of __func__ outside a function, because nothing in the standard forbids an implementation from defining __func__ as a namespace-scope array of char if that's what the implementors want to do.
It could be undefined, or it could be defined as a string, or as anything else, and that implementation is still conforming.
So it's undefined behaviour to try to use it outside a function because it may or may not be defined and may or may not be of the right type to be usable.
For concrete examples of how the code in the question could have undefined behaviour when used with a conforming implementation, I believe an implementation could define it to nullptr (so the example would crash in printf) or could even define it to a macro that expands to a dereference of a null pointer and then #undef it on entry to each function and #define it after each function (so the example would crash before main begins!)
Related
Consider these two function definitions:
void foo() { }
void foo(void) { }
Is there any difference between these two? If not, why is the void argument there? Aesthetic reasons?
In C:
void foo() means "a function foo taking an unspecified number of arguments of unspecified type"
void foo(void) means "a function foo taking no arguments"
In C++:
void foo() means "a function foo taking no arguments"
void foo(void) means "a function foo taking no arguments"
By writing foo(void), therefore, we achieve the same interpretation across both languages and make our headers multilingual (though we usually need to do some more things to the headers to make them truly cross-language; namely, wrap them in an extern "C" if we're compiling C++).
I realize your question pertains to C++, but when it comes to C the answer can be found in K&R, pages 72-73:
Furthermore, if a function declaration does not include arguments, as
in
double atof();
that too is taken to mean that nothing is to be assumed about the
arguments of atof; all parameter checking is turned off. This special
meaning of the empty argument list is intended to permit older C
programs to compile with new compilers. But it's a bad idea to use it
with new programs. If the function takes arguments, declare them; if
it takes no arguments, use void.
C++11 N3337 standard draft
There is no difference.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
Annex C "Compatibility" C.1.7 Clause 8: declarators says:
8.3.5 Change: In C ++ , a function declared with an empty parameter list takes no arguments. In C, an empty
parameter list means that the number and type of the function arguments are unknown.
Example:
int f();
// means int f(void) in C ++
// int f( unknown ) in C
Rationale: This is to avoid erroneous function calls (i.e., function calls with the wrong number or type of
arguments).
Effect on original feature: Change to semantics of well-defined feature. This feature was marked as “obsolescent” in C.
8.5.3 functions says:
4. The parameter-declaration-clause determines the arguments that can be specified, and their processing, when
the function is called. [...] If the parameter-declaration-clause is empty, the function
takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
C99
As mentioned by C++11, int f() specifies nothing about the arguments, and is obsolescent.
It can either lead to working code or UB.
I have interpreted the C99 standard in detail at: https://stackoverflow.com/a/36292431/895245
In C, you use a void in an empty function reference so that the compiler has a prototype, and that prototype has "no arguments". In C++, you don't have to tell the compiler that you have a prototype because you can't leave out the prototype.
Is the result of the following code defined in C or C++?
#define FOO
#define BAR defined(FOO)
#if BAR
int x = 1;
#else
int x = 2;
#endif
Using defined as an expansion in conditional directive is considered as Undefined Behavior.
From C99 Standard: 6.10.1/4 | C++11 Standard Last Working Draft(n4296) 16.1/4
If the token defined is generated as a result of this replacement
process or use of the defined unary operator does not match one of the
two specified forms prior to macro replacement, the behavior is
undefined.
From C99 Standard: 6.10.8/4 | C++11 Standard Last Working Draft(n4296) 16.8/4
None of these macro names, nor the identifier defined, shall be the
subject of a #define or a #undef preprocessing directive.
GNU - CPP 4.2.3
If the defined operator appears as a result of a macro expansion, the
C standard says the behavior is undefined. GNU cpp treats it as a
genuine defined operator and evaluates it normally. It will warn
wherever your code uses this feature if you use the command-line
option ‘-pedantic’, since other compilers may handle it differently.
When you attempt to use constexpr with main like this:
constexpr int main()
gcc and clang complain:
error: cannot declare '::main' to be inline
error: 'main' is not allowed to be declared constexpr
Let's see what requirements for constexpr function are:
A constexpr function must satisfy the following requirements:
it must not be virtual
its return type must be LiteralType
each of its parameters must be literal type
What is LiteralType?
A literal type is any of the following
void(since c++14)
scalar type
reference type
an array of literal type
What must the function body include?
null statements
static_assert declarations
typedef declarations and alias declarations that do not define classes or enumerations
using declarations
using directives
exactly one return statement that contains only literal values, constexpr variables and functions.
The following examples:
constexpr int main() { ; }
constexpr int main() { return 42; }
constexpr int main() {
// main defaults to return 0
}
seems to fit all these requirements. Also with that, main is special function that runs at start of program before everything else. You can run constexpr functions from main, and in order for something marked constexpr to be constexpr, it must be run in a constexpr context.
So why is main not allowed to be a constexpr?
No, this is not allowed the draft C++ standard in section 3.6.1 Main function paragraph 3 says:
[...]A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-formed.[...]
main has to be a run-time function and as Lightness says it makes no sense since you can't optimize main away.
The standard gives the precise signature for main, so the compiler is allowed to reject other signatures. Even more specifically, it prescribes that main cannot be constexpr, static, or some other things.
If you're wondering why, the compiler is allowed to insert code at the beginning of main (to do stuff like initialize global variables, etc.) which could make it non-constexpr (which is why e.g. a program is not allowed to call main explicitly).
It doesn't make any sense to declare main as constexpr for two reasons: 1) It is a run-time function. 2) it may not be called from other functions or recursively.
In my opinion the reason is that it makes no sense to declare main() as a constexpr and the standards committee want the C++ programming language to make sense.
The function main() is a special function that deals with program entry-point initialization - it is not sensible to use it to calculate compile-time values.
I'm a newbie to C++. I don't understand why it is okay (i.e. why the compiler allows it) for 1 function to be declared twice. For example, the following code is legal:
#include <iostream>
#include <string>
int hello();
int hello();
int main(){
cout << "hello, world" << endl;
}
int hello(){
return 1;
}
Why does the compiler not complain?
In C and C++ forward declarations are very weak. They provide a formal "promise" to the compiler that if a function with a specified signature appears at all, it would have the signature that you specify. The function is not even guaranteed to appear: unless you call or otherwise reference the declared function, the compiler is not going to complain that there is a declaration with no definition. The standard requires compilers to treat identical forward declarations as a single declaration.
Unlike definitions which must be unique according to the single definition rule
3.2 No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template
declarations are merely required to refer to the same definition, i.e. be equivalent to each other:
3.3.4 Given a set of declarations in the same declarative region, each of which specifies the same unqualified name, they shall all refer to the same entity, or all refer to functions or function templates, [...]
Your doubt will be cleared by "One Definition Rule". It is defined in the ISO C++ Standard (ISO/IEC 14882) 2003, at section 3.2.
It states that:
In any translation unit, a template, type, function, or object can
have no more than one definition. Some of these can have any number of
declarations.
Read more about it on Wikipedia (http://en.wikipedia.org/wiki/One_Definition_Rule)
I noticed a very curious behavior that, if standard, I would be very happy to exploit (what I'd like to do with it is fairly complex to explain and irrelevant to the question).
The behavior is:
static void name();
void name() {
/* This function is now static, even if in the declaration
* there is no static keyword. Tested on GCC and VS. */
}
What's curious is that the inverse produces a compile time error:
void name();
static void name() {
/* Illegal */
}
So, is this standard and can I expect other compilers to behave the same way? Thanks!
C++ standard:
7.1.1/6: "A name declared in a namespace scope without a
storage-class-specifier has external
linkage unless it has internal linkage
because of a previous declaration" [or unless it's const].
In your first case, name is declared in a namespace scope (specifically, the global namespace). The first declaration therefore alters the linkage of the second declaration.
The inverse is banned because:
7.1.1/7: "The linkages implied by successive declarations for a given
entity shall agree".
So, in your second example, the first declaration has external linkage (by 7.1.1/6), and the second has internal linkage (explicitly), and these do not agree.
You also ask about C, and I imagine it's the same sort of thing. But I have the C++ book right here, whereas you're as capable of looking in a draft C standard online as I am ;-)
Qualifiers that you put on the function prototype (or that are implied) are automatically used when the function is declared.
So in your second case the lack of static on the prototype meant that the function was defined as NOT static, and then when it was later declared as static, that was an error.
If you were to leave off the return type in the prototype, then the default would be int and then you would get an error again with the void return type. The same thing happens with __crtapi and __stdcall and __declspec() (in the Microsoft C compiler).