Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Look into the ISO/IEC 9899:1999, chapter 6.10.3.1. It states that:</p> <blockquote> <p><strong>After</strong> the arguments for the invocation of a function-like macro have been <em>identified</em>, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument <strong>after</strong> all macros contained therein have been expanded. <strong>Before</strong> being substituted, <em>each argument’s preprocessing tokens are completely macro replaced</em> as if they formed the rest of the preprocessing file; no other preprocessing tokens are available.</p> </blockquote> <p>So in <em>va</em> the first argument <em>c</em> has one preprocessing token being <code>__VA_ARGS__</code>, which, according to this paragraph, must be <em>macro replaced</em> before being substituted to <em>c</em> (which still does not give the answer as to which compiler is right)</p> <p>But later:</p> <blockquote> <p>An identifier <code>__VA_ARGS__</code> that occurs in the replacement list shall be treated as if it were a <strong>parameter</strong>, and the variable arguments shall form the preprocessing tokens used to replace it.</p> </blockquote> <p>According to the first fragment, first the arguments to <em>var</em> are identified. They are: <code>2</code>, <code>3</code>, <code>printf</code>, <code>“%d %d %d\n”</code> and <code>1</code>. Now argument substitution takes place. This means that parameters from <em>var</em>'s replacement list are taken and replaced. However, the second fragment states, that identifier <code>__VA_ARGS__</code> is to be treated as a parameter, so it must be substituted to <code>printf, “%d %d %d\n”, 1</code>. Now there are no macros inside parameters, so no further substitution takes place, resulting in the expansion of <code>var(2, 3, printf, “%d %d %d\n”, 1);</code> into <code>va(printf, “%d %d %d\n”, 1, 2, 3);</code>. Because va is a macro, it is also expanded, giving the result of <code>printf(“%d %d %d\n”, 1, 2, 3);</code>. Now if you take VS 2008's reasoning, how can it <em>identify</em> the arguments to <em>va</em>, if one of them is <code>__VA_ARGS__</code> from <em>var</em>, and can contain many arguments? Well, it treats <code>__VA_ARGS__</code> as an argument to <em>va</em>, which in my opition is wrong, as, according to fragment one, argument substitution takes place only <em>after</em> the arguments for invocation have been identified.</p> <p>So it seems to me, that in <em>var</em> the preprocessor has to first identify the arguments to the invocation of the macro <em>va</em>, and then start expanding <em>va</em>. And this means that probably gcc is right here.</p> <p>It is also shown in <a href="https://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation">C preprocessor and concatenation</a> how processing tokens are macro-replaced in order, until there are no identifiers which can be further expanded as macros, or the preprocessor spots a recursion and terminates expansion.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload