Printing the variable identifier formed by the preprocessor - c

How to retrieve the text expanded from a macro?
#include <stdio.h>
#define paste(front, back) front ## back
int main()
{
int number1 = 23;
int number2 = 64;
printf("%d\n", paste(number, 2));
return 0;
}
The output is: 64 because the macro is expanded as:
printf("%d\n", number2);
How can I print the identifier number2 as string by using the defined paste macro. I need to know how to create the output:
number2: 64 by not writing directly "number2" I don't want this solution:
printf("number2: %d\n", paste(number, 2))
I want a dynamic solution. I try to concatenate by doing:
printf("%s: %d\n", paste(number, 2), paste(number, 2));
But it doesn't work because number2 returned by the paste macro is an the identifier an integer How can I retrieve as a text (string)?

Use the stringizing directive #:
#define stringize_impl(x) #x
#define stringize(x) stringize_impl(x)
printf("%s: %d\n", stringize(paste(number, 2)), paste(number, 2));
On a side note: why are you trying to do this? Surely there must be a better solution.

If you're compiling with GCC you can call it with gcc -E filename.c to see the expansion of macros.
EDIT:
You can also use the stringize preprocessor operator # that effectively puts double-quotes around the right-hand symbol.
#include <stdio.h>
#define T(...) #__VA_ARGS__
#define paste(f, b) _paste(f, b)
#define _paste(front, back) front##back
int main()
{
int n = 5;
printf("macro expands to: '%s'\n", T(paste(number, 2), paste(number, 2)));
printf("macro expands to: '%s'\n", T(paste(n, 2)));
return 0;
}
This code hopefully answers the question.
You need to expand the macro one more time to expand the paste in the stringize. In other words, for the paste macro inside the stringize macro to expand, the preprocessor has to pass over the file one more time. That's why you pass it through another macro defined later in the file.
I'm not 100% sure of ALL the rules of the preprocessor, but this seems to hold pretty well. For every macro you want to expand inside another macro, you need to do some magic to force the preprocessor to pass over the file again :) There exist different ways of achieving this to my knowledge, but this is one.
EDIT2:
Edited the code. I am getting this output, is this what you want?
morten#laptop:/tmp$ ./a.out
macro expands to: 'paste(number, 2), paste(number, 2)'
macro expands to: 'paste(n, 2)'

Related

Passing macro arguments to macro function

How do I pass macro arguments along with another integer variable to a macro function?
#define SUM(X, Y, Z) X + Y + Z
#define FOO 1, 2
void print(int a, int b)
{
printf("Sum: %d", a + b);
}
int main(void)
{
// Normal function works as expected
print(FOO);
// Macro function not working
int a = 3;
printf("\nMacro Sum: %d", SUM(FOO, a));
return 0;
}
I expect the output to be:
Sum: 3
Macro Sum: 6
However, I get the following error:
main.c:18:41: error: macro "SUM" requires 3 arguments, but only 2 given
printf("\nMacro Sum: %d", SUM(FOO, a));
Macro arguments are not expanded when the macro call is parsed. After the macro call is parsed, each use of a macro parameter in the macro definition text is replaced with the macro-expanded argument, except for macro parameters used with the # or ## operations (stringify and token paste), which are replaced with the unexpanded text of the macro argument. Then the # and ## operations are performed, and then the entire macro body is scanned one more time.
The consequence is that SUM(FOO, a) is parsed aa having two arguments. Since the macro requires three, thatvwon't compile.
You can work around this, to some extent, by using one extra level of macro expansion:
#define CALL(macro, ...) macro(__VA_ARGS__)
printf("\nMacro Sum: %d", CALL(SUM, FOO, a));
Now the use of the __VA_ARGS__ parameter (which happens to be a varargs parameter, although that makes absolutely no difference to the expansion order) will be expanded before the replacement text is rescanned, so FOO will be invoked with three arguments.
By the way, outputting a newline character at the beginning of an output line is a bad habit which will get you into trouble someday. Output lines should have a newline at the end of the line:
printf("Macro Sum: %d\n", CALL(SUM, FOO, a));
There is nothing wrong with also writing a blank line beforehand by putting a newline at the beginning as well, but regardless, you should almost always terminate outpur lines with the \n. Otherwise:
The line might not be written immediately. Line-buffered output is not actually sent to the output device/file until a newline is sent.
If the program is a console app and it terminates without properly closing stdout, you will find yourself typing the next shell command at rhe end if the last output line. This tends to confuse line-editing input libraries like readline.
Single macro argument would work:
#define SUM(X, Y, Z) X + Y + Z
#define FOO1 (1)
#define FOO2 (2)
void print(int a, int b)
{
printf("Sum: %d", a + b);
}
int main(void)
{
// Normal function works as expected
print(FOO1,FOO2);
int a = 3;
printf("\nMacro Sum: %d", SUM(FOO1, FOO2, a));
return 0;
}
Output:
Sum: 3
Macro Sum: 6

mixture of string and number in macro

I want to use this macro to put (if 'i' is greater than zero) the symbol '^' and the number I pass (i) to the macro
#define ESP(i) ((i>0) ? ("^"(i)) : "")
I want to call it in this way
printf("%+d%s", n1, ESP(i));
where 'i' is the index of a cycle, but the compilation reports me errors;
how can I modify the code to be right?
Somewhat dirty but should work:
#include <stdio.h>
#define DYNFORMAT(n, i) (i>0) ?"%+d%s%d\n" :"%+d%s%s\n", n, (i>0) ?"^" :"", (i>0) ?i :""
int main(void)
{
int i = 0;
printf(DYNFORMAT(42, i));
i = 1;
printf(DYNFORMAT(42, i));
}
This should print:
+42
+42^1
Disclaimer: I am not sure whether this conforms to the Standard and how to get rid of the warning(s) it gives during compilation.
The clean approach would be to use two calls to printf().
This can be implemented as a macro or a function.
As I love the pre-processor, the macro version here:
#define PRINT_ESP(n, i) \
do { \
if (i = 0) \
printf("%+d", n); \
else \
printf("%+d^%d", n, i); \
} while (0);
Macros operate at compile time, not at run time. They can perform a variety of text-mangling tricks, but they do not evaluate anything. (They can certainly, however, expand to code that evaluates something.) Putting the formatted value of variable i into a string involves evaluating i; no macro can do this.
You could instead expand the scope of the macro to include the whole printf() call:
#define PRINT_ESP(n1, i) do { \
printf(((i > 0) ? "%+d^%d" : "%+d"), n1, i); \
} while (0)
Alternatively, you could use a macro to express just the format selection incorporated into the above macro definition, or you could just put the full printf() call above directly into your code.
All of these variations are based on the fact that arguments in excess of those required by the given format are evaluated prior to the call, but ignored by printf() itself.
You don't need the (i) after the "^". Change your macro to this and it should work #define ESP(i) ((i>0) ? ("^") : ("")). Then in your printf statement if you want to print the value of i after the "^" then have something like this printf("%s%d", ESP(i), i); As far as I know I don't think you can format a string to include an integer inside a macro since that would require calling other functions, so you have to bring the i into the string inside your printf.

Arithmetic Expressions as argument to macro in c

using macro with preprocessor directive #define I have written the following two codes.
first code passes the expression e.g. a+b
_valid_pagesize(a+b)
in second code
c=a+b
and then passed this c as an argument to macro.
_valid_pagesize(c)
the second code runs perfectly whereas the first code doesn't.
can we not pass expressions as arguments to macro like the way we can in case of a function..?
why not..?
the code passing expression as argument :
#include<stdio.h>
#include<stdlib.h>
#define _valid_pagesize(_newsize) (!(_newsize % 0x80000000)?1: \
(!(_newsize % 0x40000000)?1: \
(!(_newsize % 0x10000000)?1: \
(!(_newsize % 0x4000000) ?1:0))))
int main(int argc, char* argv[]){
uint64_t size[2];
size[0]=atoi(argv[1]);
size[1]=atoi(argv[2]);
if(_valid_pagesize(size[0]+size[1])){
printf("success\n");
}
return 0;
}
Rule #1 with macros is to enclose all arguments in parentheses, to avoid exactly the problem that you're seeing.
#define _valid_pagesize(_newsize) (!((_newsize) % 0x80000000)?1: \
(!((_newsize) % 0x40000000)?1: \
(!((_newsize) % 0x10000000)?1: \
(!((_newsize) % 0x4000000) ?1:0))))
When you pass a+b to the macro, it expands to
a + b % 0x40000000
and since % has higher precedence than +, you don't get the result you expect. By enclosing the argument in parentheses, the macro expands to
(a + b) % 0x40000000
which works as expected.
Macro parameters aren't evaluated prior to being passed to the macro, since macro expansion occurs prior to compilation. Instead, the actual expression is passed unchanged into the macro, and is substituted into all occurrences of the parameter name. Therefore, _valid_pagesize(a+b) expands to this:
(!(a+b % 0x80000000)?1: \
(!(a+b % 0x40000000)?1: \
(!(a+b % 0x10000000)?1: \
(!(a+b % 0x4000000) ?1:0))))
Now, the reason it produces wrong answers is hopefully obvious. Follow user3386109's advice about enclosing the parameter in parentheses.
Put _newsize inside braces in the macro expansion

Renaming a macro in C

Let's say I have already defined 9 macros from
ABC_1 to ABC_9
If there is another macro XYZ(num) whose objective is to call one of the ABC_{i} based on the value of num, what is a good way to do this? i.e. XYZ(num) should call/return ABC_num.
This is what the concatenation operator ## is for:
#define XYZ(num) ABC_ ## num
Arguments to macros that use concatenation (and are used with the operator) are evaluated differently, however (they aren't evaluated before being used with ##, to allow name-pasting, only in the rescan pass), so if the number is stored in a second macro (or the result of any kind of expansion, rather than a plain literal) you'll need another layer of evaluation:
#define XYZ(num) XYZ_(num)
#define XYZ_(num) ABC_ ## num
In the comments you say that num should be a variable, not a constant. The preprocessor builds compile-time expressions, not dynamic ones, so a macro isn't really going to be very useful here.
If you really wanted XYZ to have a macro definition, you could use something like this:
#define XYZ(num) ((int[]){ \
0, ABC_1, ABC_2, ABC_3, ABC_4, ABC_5, ABC_6, ABC_7, ABC_8, ABC_9 \
}[num])
Assuming ABC_{i} are defined as int values (at any rate they must all be the same type - this applies to any method of dynamically selecting one of them), this selects one with a dynamic num by building a temporary array and selecting from it.
This has no obvious advantages over a completely non-macro solution, though. (Even if you wanted to use macro metaprogramming to generate the list of names, you could still do that in a function or array definition.)
Yes, that's possible, using concatenation. For example:
#define FOO(x, y) BAR ##x(y)
#define BAR1(y) "hello " #y
#define BAR2(y) int y()
#define BAR3(y) return y
FOO(2, main)
{
puts(FOO(1, world));
FOO(3, 0);
}
This becomes:
int main()
{
puts("hello " "world");
return 0;
}

macro arguments

What will the program print when the inputs are 2,3?
#include <stdio.h>
#define min(a,b) ((a) > (b) ? (b) : (a))
#define inc(a) a++
#define mult(a,b) (a * b)
int main(void) {
int x = 1, y = 2;
scanf("%d %d",&x,&y);
printf("min(%d,inc(%d))",x,y);
printf("=%d\n",min(x,inc(y)));
printf("min(mult(%d,%d+2),11)",x,y);
printf("=%d\n",min(mult(x,y+2),11));
return 0;
}
edit: I get funny answer for negative numbers i.e -1,-2.
Why is inc(-2) change y to zero instead of -1?
Think of a macro as simply string replacement. Just replace the macro name and parentheses with the body of the macro definition, replacing the macro parameters with what is passed in. An example is easier:
#define hello(a) a+a
...
int y = hello(x);
Would be replaced with:
int y = x+x;
To answer your question, do this manually, and very, very carefully. For nested macros, start with the inside one. Did I mention do this carefully? Don't add or remove any sets of parentheses.
The output would be:
min(2,inc(3))=2
min(mult(2,4+2),11)=11
What do you mean with overwrite?
If you define a function like you did above and call for example this:
inc(x);
.. then the compiler turns it into x++. The variable a is just a name for the "paramter" and will also be replaced by the real variable.
What operating system are you running? you can easily run this yourself and see the results
if your on Windows I would suggest getting CodeBlocks or Visual Studios
if your on Linux or MAC , learn to compile from terminal using gcc or g++

Resources