Standard Behavior Of Function-Like Macro With Empty Argument Next To ## Operator?
Take the following example:
#define FOO(x) bar x ## baz
FOO( )
What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?
I ran the above through gcc -E
and clang -E
, and both produced output equivalent to the following:
bar baz
Also, if the above preprocessed output is considered to conform to the standards, then what about this?
#define FOO(x) x ## baz
FOO( )
With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror
flags):
baz
The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:
6.8.3.3 The ## operator
A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.
If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x
does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz
.
Furthermore, the standard states:
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
So, considering the first example I gave above, why shouldn't the correct output be, say, this?
barbaz
UPDATE
As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:
gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -
The output (with error) is:
foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"
bar baz
cc1: all warnings being treated as errors
The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.
Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.
c c-preprocessor preprocessor
add a comment |
Take the following example:
#define FOO(x) bar x ## baz
FOO( )
What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?
I ran the above through gcc -E
and clang -E
, and both produced output equivalent to the following:
bar baz
Also, if the above preprocessed output is considered to conform to the standards, then what about this?
#define FOO(x) x ## baz
FOO( )
With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror
flags):
baz
The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:
6.8.3.3 The ## operator
A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.
If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x
does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz
.
Furthermore, the standard states:
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
So, considering the first example I gave above, why shouldn't the correct output be, say, this?
barbaz
UPDATE
As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:
gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -
The output (with error) is:
foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"
bar baz
cc1: all warnings being treated as errors
The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.
Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.
c c-preprocessor preprocessor
If you want to achievebarbaz
you need two token-pasting operators:#define FOO(x) bar ## x ## baz
. This works withFOO(X)
as well as withFOO()
. (I just tried withecho -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)
– Scheff
Nov 20 '18 at 6:33
@4386427 Sorry, that's a typo in my question. I meant to writebaz
. Fixing that now.
– jinscoe123
Nov 20 '18 at 6:36
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
OK. As I understand token-pasting, with#define FOO(x) bar x ## baz
andFOO(X)
the expected isbar Xbaz
, and forFOO()
the expected isbar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
– Scheff
Nov 20 '18 at 6:42
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50
add a comment |
Take the following example:
#define FOO(x) bar x ## baz
FOO( )
What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?
I ran the above through gcc -E
and clang -E
, and both produced output equivalent to the following:
bar baz
Also, if the above preprocessed output is considered to conform to the standards, then what about this?
#define FOO(x) x ## baz
FOO( )
With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror
flags):
baz
The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:
6.8.3.3 The ## operator
A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.
If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x
does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz
.
Furthermore, the standard states:
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
So, considering the first example I gave above, why shouldn't the correct output be, say, this?
barbaz
UPDATE
As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:
gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -
The output (with error) is:
foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"
bar baz
cc1: all warnings being treated as errors
The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.
Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.
c c-preprocessor preprocessor
Take the following example:
#define FOO(x) bar x ## baz
FOO( )
What is the expected output of the above code, according to the ANSI C and C99 standards, after the preprocessing phase?
I ran the above through gcc -E
and clang -E
, and both produced output equivalent to the following:
bar baz
Also, if the above preprocessed output is considered to conform to the standards, then what about this?
#define FOO(x) x ## baz
FOO( )
With the above modification GCC and clang still produce output equivalent to the following, without emitting any warning or error (even with the -Wall -Werror
flags):
baz
The reason I am suspicious that the above output is not conformant to the standards is that the ANSI C 9899:1990 standard states:
6.8.3.3 The ## operator
A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for either form of macro definition.
If, in the replacement list, a parameter is immediately preceded or followed by a ## preprocessing token, the parameter is replaced by the corresponding argument's preprocessing token sequence.
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples, but x
does expand to... a single space? nothing? ...so the ## operator (at least, as I understand it) is concatenating a space pp-token (or nothing) to baz
.
Furthermore, the standard states:
For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
So, considering the first example I gave above, why shouldn't the correct output be, say, this?
barbaz
UPDATE
As a sidenote, I did manage to get GCC to emit an error for the first example I gave above when preprocessing the code as follows:
gcc -ansi -pedantic -Wall -Werror -E ex1.c -o -
The output (with error) is:
foo.c:2:6: error: invoking macro FOO argument 1: empty macro arguments are undefined in ISO C90 [-Werror=pedantic]
FOO( )
^
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "foo.c"
bar baz
cc1: all warnings being treated as errors
The error, however, is not related to the behavior of the ## operator, which is what this question was all about. It's still interesting nonetheless.
Also interesting to note is that no error is emitted by clang when preprocessing the file, using the same flags.
c c-preprocessor preprocessor
c c-preprocessor preprocessor
edited Nov 20 '18 at 8:02
jinscoe123
asked Nov 20 '18 at 6:17
jinscoe123jinscoe123
214212
214212
If you want to achievebarbaz
you need two token-pasting operators:#define FOO(x) bar ## x ## baz
. This works withFOO(X)
as well as withFOO()
. (I just tried withecho -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)
– Scheff
Nov 20 '18 at 6:33
@4386427 Sorry, that's a typo in my question. I meant to writebaz
. Fixing that now.
– jinscoe123
Nov 20 '18 at 6:36
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
OK. As I understand token-pasting, with#define FOO(x) bar x ## baz
andFOO(X)
the expected isbar Xbaz
, and forFOO()
the expected isbar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
– Scheff
Nov 20 '18 at 6:42
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50
add a comment |
If you want to achievebarbaz
you need two token-pasting operators:#define FOO(x) bar ## x ## baz
. This works withFOO(X)
as well as withFOO()
. (I just tried withecho -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)
– Scheff
Nov 20 '18 at 6:33
@4386427 Sorry, that's a typo in my question. I meant to writebaz
. Fixing that now.
– jinscoe123
Nov 20 '18 at 6:36
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
OK. As I understand token-pasting, with#define FOO(x) bar x ## baz
andFOO(X)
the expected isbar Xbaz
, and forFOO()
the expected isbar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)
– Scheff
Nov 20 '18 at 6:42
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50
If you want to achieve
barbaz
you need two token-pasting operators: #define FOO(x) bar ## x ## baz
. This works with FOO(X)
as well as with FOO()
. (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)– Scheff
Nov 20 '18 at 6:33
If you want to achieve
barbaz
you need two token-pasting operators: #define FOO(x) bar ## x ## baz
. This works with FOO(X)
as well as with FOO()
. (I just tried with echo -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)– Scheff
Nov 20 '18 at 6:33
@4386427 Sorry, that's a typo in my question. I meant to write
baz
. Fixing that now.– jinscoe123
Nov 20 '18 at 6:36
@4386427 Sorry, that's a typo in my question. I meant to write
baz
. Fixing that now.– jinscoe123
Nov 20 '18 at 6:36
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
OK. As I understand token-pasting, with
#define FOO(x) bar x ## baz
and FOO(X)
the expected is bar Xbaz
, and for FOO()
the expected is bar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)– Scheff
Nov 20 '18 at 6:42
OK. As I understand token-pasting, with
#define FOO(x) bar x ## baz
and FOO(X)
the expected is bar Xbaz
, and for FOO()
the expected is bar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)– Scheff
Nov 20 '18 at 6:42
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50
add a comment |
2 Answers
2
active
oldest
votes
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,
The word "technically" here is redundant. The replacement list of both of your macros has x
before the ##
, so that rule doesn't apply.
but x does expand to... a single space? nothing?
6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.
So your whitespace in your argument to FOO
is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:
6.10.3.3 p2:
however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.
The next paragraph, 3, applies to the result here:
concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
So, placemarker pasted onto baz
produces baz
.
add a comment |
If you have this:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
. So the space in the FOO call is not relevant.
If you have this:
#define FOO(x) bar ## x ## baz
FOO();
you get barbaz
because you ask to get all those pasted together.
But you write:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
because you ask for bar
and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz
that gives you bar,baz
.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387287%2fstandard-behavior-of-function-like-macro-with-empty-argument-next-to-operator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,
The word "technically" here is redundant. The replacement list of both of your macros has x
before the ##
, so that rule doesn't apply.
but x does expand to... a single space? nothing?
6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.
So your whitespace in your argument to FOO
is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:
6.10.3.3 p2:
however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.
The next paragraph, 3, applies to the result here:
concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
So, placemarker pasted onto baz
produces baz
.
add a comment |
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,
The word "technically" here is redundant. The replacement list of both of your macros has x
before the ##
, so that rule doesn't apply.
but x does expand to... a single space? nothing?
6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.
So your whitespace in your argument to FOO
is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:
6.10.3.3 p2:
however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.
The next paragraph, 3, applies to the result here:
concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
So, placemarker pasted onto baz
produces baz
.
add a comment |
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,
The word "technically" here is redundant. The replacement list of both of your macros has x
before the ##
, so that rule doesn't apply.
but x does expand to... a single space? nothing?
6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.
So your whitespace in your argument to FOO
is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:
6.10.3.3 p2:
however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.
The next paragraph, 3, applies to the result here:
concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
So, placemarker pasted onto baz
produces baz
.
Okay, so technically the ## operator is NOT at the beginning of the replacement list in both of the above two examples,
The word "technically" here is redundant. The replacement list of both of your macros has x
before the ##
, so that rule doesn't apply.
but x does expand to... a single space? nothing?
6.4 lists what's considered preprocessing tokens: header-name, identifier, pp-number, character-constant, string-literal, punctuator, and "each non-whitespace character that cannot be one of the above". Note what is conspicuously absent from this list... whitespace in and of itself.
So your whitespace in your argument to FOO
is not significant; your argument is a sequence of 0 preprocessing tokens (that is, 0 of the things in that list above). That means that this applies:
6.10.3.3 p2:
however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.
The next paragraph, 3, applies to the result here:
concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token.
So, placemarker pasted onto baz
produces baz
.
answered Nov 20 '18 at 7:15
H WaltersH Walters
1,671159
1,671159
add a comment |
add a comment |
If you have this:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
. So the space in the FOO call is not relevant.
If you have this:
#define FOO(x) bar ## x ## baz
FOO();
you get barbaz
because you ask to get all those pasted together.
But you write:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
because you ask for bar
and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz
that gives you bar,baz
.
add a comment |
If you have this:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
. So the space in the FOO call is not relevant.
If you have this:
#define FOO(x) bar ## x ## baz
FOO();
you get barbaz
because you ask to get all those pasted together.
But you write:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
because you ask for bar
and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz
that gives you bar,baz
.
add a comment |
If you have this:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
. So the space in the FOO call is not relevant.
If you have this:
#define FOO(x) bar ## x ## baz
FOO();
you get barbaz
because you ask to get all those pasted together.
But you write:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
because you ask for bar
and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz
that gives you bar,baz
.
If you have this:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
. So the space in the FOO call is not relevant.
If you have this:
#define FOO(x) bar ## x ## baz
FOO();
you get barbaz
because you ask to get all those pasted together.
But you write:
#define FOO(x) bar x ## baz
FOO();
You get bar baz
because you ask for bar
and the paste of x and baz. Which is similar to #define FOO(x) bar,x ## baz
that gives you bar,baz
.
answered Nov 20 '18 at 7:00
perrealperreal
72.4k9111138
72.4k9111138
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53387287%2fstandard-behavior-of-function-like-macro-with-empty-argument-next-to-operator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
If you want to achieve
barbaz
you need two token-pasting operators:#define FOO(x) bar ## x ## baz
. This works withFOO(X)
as well as withFOO()
. (I just tried withecho -e '#define FOO(x) bar ## x ## baznFOO(x)nFOO()n' | gcc -std=c99 -E -
, although I was actually sure about this.) ;-)– Scheff
Nov 20 '18 at 6:33
@4386427 Sorry, that's a typo in my question. I meant to write
baz
. Fixing that now.– jinscoe123
Nov 20 '18 at 6:36
@Scheff Thanks, but I'm not trying to achieve anything in particular with the above code. I'm writing a C preprocessor, and I'd like to know what is the standard behavior of the above code snippets, so that I know what is the proper way to handle these corner cases.
– jinscoe123
Nov 20 '18 at 6:39
OK. As I understand token-pasting, with
#define FOO(x) bar x ## baz
andFOO(X)
the expected isbar Xbaz
, and forFOO()
the expected isbar baz
. The token-pasting connects left and right, even if left or right is a macro argument which is left empty. And, this is what you described in your question. Standard texts are somehow hard to understand sometimes (at least for me). But the token-pasting itself is rather simple (for me). ;-)– Scheff
Nov 20 '18 at 6:42
I once wrote a pre-processor, but I didn't make it perfect. To keep it simple, it reads and writes an ASCII stream (not a token stream). Additionally, I didn't implement blue-painting - it just processes stream from begin to end (no repeating). For what I wanted to use it, this was sufficient but things like this C Preprocessor tricks, tips, and idioms will surely not work. (I even didn't try.) ;-)
– Scheff
Nov 20 '18 at 6:50