Comma-Operator in Preprocessor-Directives

In fact this is a question for deeper understanding.

Let's say I have the following code:

#define DEF 1,2,3
#if (DEF > 3)
#endif

If I am right the if should always be true, as 1 and 2 are Expressions that have no affect and only 3 will be checked. (This should at least be true in normal C/C++-code)

But is that right or would there be any Reason why I should think about 1 and 2, too? I saw it in some code and am not really sure if this could have any sense or affect.

Answers


Your example code is not strictly conforming.

From C11, 6.10.1 par. 3 (Conditional inclusion, Semantics):

Preprocessing directives of the forms

# if constant-expression new-line groupopt

# elif constant-expression new-line groupopt

check whether the controlling constant expression evaluates to nonzero

However 6.6 par. 3 (Constant expressions, Constraints) says:

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is not evaluated.115)

Footnote 115 is:

The operand of a sizeof or _Alignof operator is usually not evaluated (6.5.3.4).


DEF will expand to give #if (1, 2, 3 > 3). Because , has low precedence, the only expression that "does" anything is 3 > 3 which, of course, is false.


#define DEF 1,2,3
#if (DEF > 3)
#endif

The above if condition will fail. Reason 3 > 3 is false. Probably you can put it as

#define DEF 1,2,3
#if (DEF == 3)
#endif

Yes, you are correct as the first two are dummy expressions only the third expression will be actually evaluated.

Consider the code:

#define DEF 1,2,3
#if (DEF > 3)
#endif

which will be treated as:

#if (1,2,3 > 3)
#endif

Precedence of , is lower than > and thus 3 > 3 results into 0. Then, #if (1,2,0) will definitely evaluated as #if (0) which is always false value.


The C++11 standard allows the comma operator, but the change was only inadvertent. Implementations such as Clang and GCC evaluate #if (1,0), but they will issue a warning under -pedantic which, though definitely a mild consequence, is their typical response to illegal preprocessor constructs. They do the same thing for macro redefinitions, which are totally harmful.

warning: comma operator in operand of #if [-Wpedantic]

The "feature" is scheduled (DR 1436) to be removed back out of the standard, but there is ongoing uncertainty as to how to do this, or how to approach maintenance of the preprocessor standard in general.

(To be clear, in the C language and C++ before C++11, the comma was specifically prohibited from constant expressions. See cremno's answer. The inadvertent change was to remove "constant expressions shall not contain…" for the general language, but without adding the rule back for the preprocessor.)

I have proposed (N4220) a comprehensive update to the preprocessor specification, but it has stalled in a subcommittee without official review. Nevertheless, several interested committee members (from Clang, GCC, and IBM XLC) did review it, and there's general agreement that the adjustments in that paper reflect the true intent of the standard. From §4.4 of that paper,

Note that the comma operator is not allowed even within parentheses.

In practical terms, no, the comma operator is neither portable nor future-proof. Several people have considered the question and agreed that you shouldn't use it there. Following the rules of expression evaluation, though, you're right that 1 and 2 simply get ignored.


Need Your Help

Upload image to SQL Database

c# sql sql-server-ce

I have been looking at solutions but don't know where I am doing it wrong. But I am doing it for the first time.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.