Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 491 Vote(s) - 3.53 Average
  • 1
  • 2
  • 3
  • 4
  • 5
# and ## in macros

#1
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)

int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}

Just by looking at the program one "might" expect the output to be, the same for both the printf statements. But on running the program you get it as:

bash$ ./a.out
12
f(1,2)
bash$

Why is it so?
Reply

#2
Because that is how the preprocessor works.

A single '#' will create a string from the given argument, regardless of what that argument contains, while the double '##' will create a new token by concatenating the arguments.

Try looking at the preprocessed output (for instance with `gcc -E`) if you want to understand better how the macros are evaluated.
Reply

#3
An occurrence of a parameter in a function-like macro, unless it is the operand of `#` or `##`, is expanded before substituting it and rescanning the whole for further expansion. Because `g`'s parameter *is* the operand of `#`, the argument is not expanded but instead immediately stringified (`"f(1,2)"`). Because `h`'s parameter *is not* the operand of `#` nor `##`, the argument is first expanded (`12`), then substituted (`g(12)`), then rescanning and further expansion occurs (`"12"`).
Reply

#4
Below are some related concepts to your question:


[Argument Prescan][2]:

> Macro arguments are completely macro-expanded ***before*** they are
> substituted into a macro body, unless they are ***stringified*** or ***pasted***
> with other tokens. After substitution, the entire macro body,
> including the substituted arguments, is scanned ***again*** for macros to be
> expanded. The result is that the arguments are scanned twice to expand
> macro calls in them.
>

[Stringification][3]

> When a macro parameter is used with a leading ‘#’, the preprocessor
> replaces it with the literal text of the actual argument, converted to
> a ***string constant***.

`#ABC => "ABC"` <---- Note the enclosing double quote, which is added by the stringification process.

[Token Pasting / Token Concatenation][4]:

> It is often useful to merge two tokens into one while expanding
> macros. This is called ***token pasting*** or ***token concatenation***. The ‘##’
> preprocessing operator performs token pasting. When a macro is
> expanded, the two tokens on either side of each ‘##’ operator are
> combined into a single token, which then replaces the ‘##’ and the two
> original tokens in the macro expansion.

So the detailed process of your scenario is like this:

h(f(1,2))
-> h(12) // f(1,2) pre-expanded since there's no # or ## in macro h
-> g(12) // h expanded to g
"12" // g expanded as Stringification

g(f(1,2))
-> "f(1,2)" //f(1,2) is literally strigified because of the `#` in macro g. f(1,2) is NOT expanded at all.


[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through