MISRA Discussion Forums

Full Version: Rule 19.12 (# and ## operator) real issue?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I recognize that \"The order in which # and ## operations are evaluated during macro substitution (6.10.3.2, 6.10.3.3).\" [ISO C 9899:1999 J.1 Unspecified behavior] is UNSPECIFIED behavior.

However, what is the real issue with the order of evaluation being unspecified? I realize that rule 19.13 goes even further than MISRA-C:1998 and advises that these operators not even be used at all. However, I'm wondering if someone can provide an example where the order of evaluation matters?

The only example I can think of is:
Code:
#define MYMACRO(a,b) # a ## b
MYMACRO(foo,bar)

Could produce (## evaluated first, then #):
Code:
\"foobar\"

or (# evaluated first, then ##):
Code:
\"foo\" bar

depending on the order of evaluation.

However, as long as ONLY # operators, or ONLY ## operators are used (i.e., # and ## operators are not BOTH used in the SAME macro), then I don't see a problem.

It is sometimes useful to use these operators more than once within a macro, particularly the ## operator:

Code:
#define MY_IDENTIFIER(a) PRE_##a##_SUF
MY_IDENTIFIER(foo)

Will always result in a new identifier:
Code:
PRE_foo_SUF

It doesn't matter which ## operator executes first:
Code:
PRE_##foo##_SUF -> PRE_foo##_SUF -> PRE_foo_SUF
PRE_##foo##_SUF -> PRE_##foo_SUF -> PRE_foo_SUF

Both result in the proper final identifier.

Macros can then be used to replace otherwise \"copy-and-paste\" code with a single macro. Then, changes to the repetitive code can be made in a single location (the macro) rather than duplicated across several lines of code. This minimizes \"copy-and-paste\" errors in the original code creation, as well as \"copy-and-paste\" errors in code maintenance.

Granted, the use of such macros is not extremely common or widespread. However, it does have its practical uses, and when done may require more than one ## operator within a single macro.

I just wondered if a specific example is available that shows where the order of evaluation matters or could cause a problem based on the UNSPECIFIED behavior when only one TYPE of operator (# only, or ## only) is used in a macro, but the one operator may be used MORE THAN ONCE in the same macro.

If there is no such issue, could rule 19.12 be updated to:
\"Both # and ## operators shall not be used in the same macro definition.\"
The standard allows and experience has shown that this behaviour can vary between compilers, and within the same compiler dependent on context.

Your example shows that the result can depend of the order of evaluation which is unspecifed.
I agree with the statement:
Quote:result can depend o[n] the order of evaluation which is unspecifed

... when both the # and the ## operator are in the same macro. However, can someone provide an example when only one of the operators (only #, or only ##) are used more than once in a single macro definition?

My recommendation is to use the following wording:
Quote:Rule 19.12 (req): The # and ## operators shall not be used together in the same macro definition.

Can someone comment on why the original wording would be preferred to this alternative? My second example doesn't have any issues with operator evaluation order that I can identify, yet it violates the original wording. With the updated wording, it would be okay, while the first example is still a violation -- as it should be, since it does have an issue with order of evaluation.
If the macro

Code:
#define m (a,b) a##3##b

is invoked as

Code:
m ( PRE, SUF ) = 0;

then the order of evaluation is important. The result of the ## operator
must be a valid preprocessing token.

Left-to-right evaluation gives 'PRE3' followed by 'PRE3SUF'.

However, the first expansion from right-to-left evaluation is 3SUF, which is
not a valid preprocessing token.
According to my reading of the standard, 3SUF is indeed a valid preprocessing token - it is a pp-number.
Apologies, 3SUF is indeed a pp-number and therefore a valid preprocessing token. A correct example would have been

Code:
#define m (a,b) a##.##b

as this would have resulted in .SUF which is not a single preprocessing token but the two tokens . and SUF respectively.
The previous response gives two preprocessing tokens regardless of order of evaluation of ## operators.

A better example would be:

Code:
#define m(a,b) a##.##b

m(1,e30)

which is defined on a left-to-right evaluation but undefined on right-to-left because .e30 is two preprocessing tokens.