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.
Related
Is it possible to remove standard features from C++
//Undefine some function from the standard like classes
class someclass
{
someclass(){
//Whatever
}
};
then get the error
"class undeclared identifier"
Not that I recommend it but you can use pre-processor macros to undefine anything you want.
If you compile the program below, you will get lots of errors.
#define vector
#include <vector>
int main()
{
vector<int> a;
}
You don't need the #define vector in the file. You can define it in the command used to invoke the compiler.
Note that using the above trick makes your program subject to undefined behavior:
From the C++11 Standard:
17.6.4.3 Reserved names
...
2 If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.
17.6.4.3.1 Macro names [macro.names]
1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
2 A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table [tab:identifiers.special], or to the attribute-tokens described in [dcl.attr].
I was just surprised that providing a type with two template arguments to a function-like macro resulted in the compiler complaining.
This (conceptually similar) example code:
template<typename T> struct foo{};
template<typename T, U> struct bar{};
#define p(x) printf("sizeof(" #x ") = %u\n", sizeof(x));
int main()
{
p(foo<int>); // works, of course
p(bar<int,int>); // does not work
p((bar<int,int>)); // does not work either
return 0;
}
makes GCC (6.2.0) complain macro "p" passed 2 arguments, but takes just 1.
Well, of course, the preprocessor is a preprocessor doing text replacement, it's not a real C++ compiler which understands templates or all other rules of the language.
Maybe I'm asking too much by expecting that the preprocessor recognizes the angle brackets, granted... but at least parentheses are explicitly mentioned in the specification.
16.3 (paragraphs 10 to 12) states outermost parentheses delimiting the bounded sequence of tokens. The word "outermost" suggests that there may possibly also be further (not-outermost) parentheses which the preprocessor recognizes.
Also, it explicitly states "skipping intervening matched pairs of left and right parenthesis" as well as "comma preprocessing tokens between matching inner parentheses do not separate arguments" -- which means that if I am reading correctly, then at least the last line should in my understanding pass.
What am I understanding wrong?
p((bar<int,int>)) is a valid invocation of the p macro with a single macro argument, which is (bar<int,int>). Your understanding so far is correct.
Unfortunately, its expansion includes sizeof((bar<int,int>)), and sizeof does not accept doubly-parenthesised types.
Variadic macros (C++11) work well here as an alternative.
#define p(...) printf("sizeof(" #__VA_ARGS__ ") = %u\n", sizeof(__VA_ARGS__));
Consider the following code (live example):
#define TEST_VA(mX, ...) TEST
#define STRINGIFY_IMPL(mX) #mX
#define STRINGIFY(mX) STRINGIFY_IMPL(mX)
#include <iostream>
int main()
{
std::cout << STRINGIFY(TEST_VA(1)) << std::endl;
std::cout << STRINGIFY(TEST_VA()) << std::endl;
return 0;
}
clang++ 3.4 complains:
main.cpp:9:37: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
std::cout << STRINGIFY(TEST_VA(1)) << std::endl;
^
main.cpp:1:9: note: macro 'TEST_VA' defined here
#define TEST_VA(mX, ...) TEST
^
main.cpp:10:33: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
std::cout << STRINGIFY(TEST_VA()) << std::endl;
^
main.cpp:1:9: note: macro 'TEST_VA' defined here
#define TEST_VA(mX, ...) TEST
I use some variadic macros like in the example code in my projects.
Is it safe to pass no arguments for the ... parameter of variadic macros? (Ignoring the warning, basically)
Or could it lead to problems?
Is it explicitly forbidden by the standard?
Starting from C++20, passing zero arguments to a variadic macro parameter is allowed, but Clang (at least Clang 12) doesn't respect this change yet.
So if you're targeting C++20 or newer and using -pedantic-errors, then -Wno-gnu-zero-variadic-macro-arguments is recommended.
[cpp.replace.general]/5
... there shall be at least as many arguments in the invocation as there are parameters in the macro definition (excluding the ...).
It's technically forbidden by the standard. From C++11 §16.3/4 (emphasis added):
If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments (including
those arguments consisting of no preprocessing tokens) in an invocation of a function-like macro shall equal
the number of parameters in the macro definition. Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...). There shall exist a ) preprocessing
token that terminates the invocation.
Some compilers may allow this as an extension, but if you want standards-compliant code, you should make sure to always include at least one argument for the ellipsis parameter of a variadic macro.
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!)
Is the following legal according to the C++ standard? (If the answer differs from standard to standard, I would like to know that, too.)
#define VERY_OLD_COMPILER 1
#ifdef VERY_OLD_COMPILER
#define USING_NAMESPACE_STD enum { }
#else
#define USING_NAMESPACE_STD using namespace std
#endif
USING_NAMESPACE_STD;
int main(int argc, char *argv[]) {
// etc.
The goal is to define a macro that I can invoke at the top-level and follow with a semicolon, such that it has no effect. I am pretty sure stray semicolons at the top-level are not allowed (GCC complains about them, anyway), so simply defining an empty macro does not work.
Declaring an empty anonymous struct does not work because it needs a name, and I do not want to pollute the namespace.
Does an anonymous empty enum declaration (enum { }) do the trick? It works on all of the compilers I have tried, but of course that is not the same thing as being permitted by the spec.
Any other ideas/comments welcome. Well, anything other than "throw out that compiler". Believe me, I would love to.
Looking at the latest public C++0x draft, it seems semicolons at top-level are allowed and ignored.
The grammar treats a translation-unit as a sequence of declarations, and amongst the various kinds of declarations there is an empty-declaration that is just a simple semicolon.
Pragmatic solution: considering that your VERY_OLD_COMPILER constant suggests that the whole thing is to be a part of a workaround for an older compiler, I'd just pick a solution that works with this compiler, be it standardised or not.
#define USING_NAMESPACE_STD static int dummy##__LINE__
An empty enum is in fact illegal according to C++03:
7/3 Declarations:
In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (clause 9) or enumeration (7.2), that is, when the decl-specifier-seq contains either a class-specifier, an elaboratedtype-specifier with a class-key (9.1), or an enum-specifier. In these cases and whenever a class-specifier or enum-specifier is present in the decl-specifier-seq, the identifiers in these specifiers are among the names eing declared by the declaration (as class-names, enum-names, or enumerators, depending on the syntax). In such cases, and except for the declaration of an unnamed bit-field (9.6), the decl-specifier-seq shall introduce one or more names into the program, or shall redeclare a name introduced by a previous declaration.
[Example:
enum { }; // ill-formed
typedef class { }; // ill-formed
—end example]
So I would agree with MSN's answer to declare a dummy enum, struct forward declaration, or typedef declaration with a name that is obviously not going to conflict with anything (throw a GUID in there for good measure). The nice thing about these things is that you can have the declaration show up more than once, and as long as it's the same as before there's no problem.
Comeau says no:
> Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for
> ONLINE_EVALUATION_BETA2 Copyright 1988-2008 Comeau Computing. All
> rights reserved. MODE:strict errors C++ C++0x_extensions
>
> "ComeauTest.c", line 1: error: declaration does not declare anything
> enum { }; ^
>
> 1 error detected in the compilation of "ComeauTest.c".
You can use
#define USING_NAMESPACE_STD struct very_long_name_that_i_hope_doesnt_collide_because_if_it_does_oh_noes
Sorry, I forgot you needed to do it at the top level.
How about
extern int _;
? I don't know what undesirable side effects this would have, though I can't think of any.
#define VERY_OLD_COMPILER 1
#ifdef VERY_OLD_COMPILER
#define USING_NAMESPACE_STD typedef unsigned long uint32
#else
#define USING_NAMESPACE_STD using namespace std
#endif
USING_NAMESPACE_STD;
Edit:
This should work also:
#define VERY_OLD_COMPILER 1
#ifdef VERY_OLD_COMPILER
#define USING_NAMESPACE_STD double fabs(double)
#else
#define USING_NAMESPACE_STD using namespace std
#endif
USING_NAMESPACE_STD;
#define VERY_OLD_COMPILER 1
#ifdef VERY_OLD_COMPILER
#define USING_NAMESPACE_STD ;
#else
#define USING_NAMESPACE_STD using namespace std
#endif
USING_NAMESPACE_STD;
int main(int argc, char *argv[]) {
// etc.