gcc dump resolved defines - c

I have code like
#define ONE 1
#define TWO 2
#define SUM (ONE+TWO)
How do I dump SUM as "3", the resolved value, in gcc 4.3+?
gcc -dM -E foo.h only seems to dump it as is. How do I get the actual value like it's inserted on compilation stage?

You can't. As far as the compiler is concerned, the line printf("%d\n", SUM) before preprocessing is indistinguishable from the line printf("%d\n", 1+2). The compiler just happens to perform an optimization called constant folding, even at the default optimization level (-O0), which turns the result into a constant 3 at runtime.
There's not really a good way to see the output of these optimizations. You could use the -S option to view the generated assembly code and see what that looks like, but if your program is anything larger than a toy, that will be a lot of manual effort. You could also look at the parse tree by using one of the -fdump-tree options (see the GCC man page).

You can't "dump" SUM as 3 because SUM isn't 3 in any meaningful sense, it's just a sequence of the three tokens ONE, + and TWO. What it turns into depends on the context where it is expanded.
Macros are expanded where they appear in the source, macro replacements are just strings of tokens until then.
You can test this like this.
#include <stdio.h>
#define ONE 1
#define TWO 2
#define SUM ONE+TWO
int a = SUM;
#undef ONE
#define ONE 2
int b = SUM;
int main()
{
printf("a = %d\nb = %d\n", a, b);
return 0;
}
Here's another example:
#include <stdio.h>
#define ONE 1
#define TWO 2
#define SUM ONE+TWO
int main()
{
/* prints 6, not 2 */
printf("5 - SUM = %d\n", 5 - SUM);
return 0;
}
With this example there's no way you can justify SUM being 3.

Contrary to the other answers, there's definitely a solution to this problem, especially with gcc extensions. Parse the output of gcc -dM and generate a C file containing lines of the form __typeof__(MACRO) foo = MACRO; and go from there. Without __typeof__ you could still handle all arithmetic types fairly well by just using long double.

One way is to stop at the precompiler stage (-E) and examine that output.

Related

Confusion about macro expansion in C

#include <stdio.h>
#define MYNUMBER 123
int main()
{
printf("%d", MYNUMBER456);
}
Above code doesn't work because MYNUMBER and MYNUMBER456 are different token.
#include <stdio.h>
#define SECOND(a, b) printf(#a #b);
#define FIRST SECOND
int main()
{
FIRST(hello, world!)
}
But this one works well. My thought is FIRST and FIRST(hello, world!) are different so it should not work. What am I missing?
You can see the macro expansion by using the -E option (cc -E main.c), though you will see a lot of other stuff inserted because of your #include <stdio.h>, and without it you will probable see some default stuff inserted, in your example the main function becomes
int main()
{
printf("hello" "world!");
}
This is because you have defined FIRST to be the same as SECOND which takes two arguments and makes them strings and since there is no comma between them they get concatenated into a single string, macros are just string substitution, in C the preprocessing is traditionally handled by a seperate executable to the compiler and is not as sophisticated as a compiler, so the type matching you would expect in most languages doesn't apply to the preprocessor.
you are correct MYNUMBER and MYNUMBER456 are different and the pre-compiler wont know how to work with MYNUMBER456
however, when you defined FIRST as SECOND , the precompiler would expand FIRST by SECOND and then you actually have SECOND with 2 parameters so it it working

C macros using enum

I am trying to use #if macros by defining the type of operation to invoke the right code, So i made a very simple example similar to what I am trying to do:
#include <stdio.h>
enum{ADD,SUB,MUL};
#define operation ADD
int main()
{
int a = 4;
int b = 2;
int c;
#if (operation == ADD)
c = a+b;
#endif
#if (operation == SUB)
c = a-b;
#endif
#if (operation == MUL)
c = a*b;
#endif
printf("result = %i",c);
return 0;
}
But unfortunately that does not work I get the following result = 8... if I replace The operation with numbers it works fine .... But i want it to work as it is described above.
Any help
The preprocessor is a step that is (in a way) done before the actual compiler sees the code. Therefore it has no idea about enumerations or their values, as they are set during compilation which happens after preprocessing.
You simply can't use preprocessor conditional compilation using enumerations.
The preprocessor will always consider that as false:
#if IDENT == IDENT
It can only test for numeric values.
Simplify your code and feed it to the preprocessor:
enum {ADD,SUB,MUL};
#define operation ADD
int main()
{
(operation == ADD);
}
The result of the preprocessor output is:
enum {ADD,SUB,MUL};
int main()
{
(ADD == ADD);
}
As you see, the enumerate value hasn't been evaluated. In the #if statement, that expression is just seen as false.
So a workaround would be to replace your enumerate by a series of #define:
#define ADD 1
#define SUB 2
#define MUL 3
like this it works. Output of preprocessor output is now:
int main()
{
int a = 4;
int b = 2;
int c;
c = a+b;
# 28 "test.c"
printf("result = %i",c);
return 0;
}
the solution is:
either rely at 100% on the preprocessor (as the solution above suggests)
or rely at 100% on the compiler (use enums and real if statements)
As others have said, the preprocessor performs its transformations at a very early phase in compilation, before enum values are known. So you can't do this test in #if.
However, you can just use an ordinary if statement. Any decent compiler with optimization enabled will detect that you're comparing constants, perform the tests at compile time, and throw out the code that will never be executed. So you'll get the same result that you were trying to achieve with #if.
But i want it to work as it is described above.
You seem to mean that you want the preprocessor to recognize the enum constants as such, and to evaluate the == expressions in that light. I'm afraid you're out of luck.
The preprocessor knows nothing about enums. It operates on a mostly-raw stream of tokens and whitespace. When it evaluates a directive such as
#if (operation == SUB)
it first performs macro expansion to produce
#if (ADD == SUB)
. Then it must somehow convert the tokens ADD and SUB to numbers, but, again, it knows nothing about enums or the C significance of the preceding code. Its rule for interpreting such symbols as numbers is simple: it replaces each with 0. The result is that all three preprocessor conditionals in your code will always evaluate to true.
If you want the preprocessor to do this then you need to define the symbols to the preprocessor. Since you're not otherwise using the enum, you might as well just replace it altogether with
#define ADD 1
#define SUB 2
#define MUL 3
If you want the enum, too, then just use different symbols with the preprocessor than you use for the enum constants. You can use the same or different values, as you like, because never the twain shall meet.
Another solution would be to have the enum in an included header file.

Can #define include previously defined variables?

How are the definitions in C processed? Are they processed in order of line numbers?
For example, will the following statements work?
#define ONE 1
#define TWO (ONE+1)
Could there be any problems with definitions that depend on previous definitions?
Yes, one #define can reference other #define substitutions and macros without any problem.
Moreover, the expression on these constants would remain a constant expression.
Your second expression would be textually equivalent to (ONE+1) replacement in the text, with no limits to the level of nesting. In other words, if you later define
#define THREE (TWO+1)
and then use it in an assignment i = THREE, you would get
i = ((ONE+1)+1)
after preprocessing.
If you are planning to use this trick with numeric values, a common alternative would be to use an enum with specific values, i.e.
enum {
ONE = 1
, TWO = ONE+1
, THREE = TWO+1
, ... // and so on
};
They're processed at point when they're used, so you example and even this
#define TWO (ONE+1)
#define ONE 1
will work.
The best way is to check by yourself:
g++ test.cpp
gcc test.c
For strict compiler check:
gcc test.c -pedantic
And all worked for me!
test.c/test.cpp
#include <stdio.h>
#define A 9
#define B A
int main()
{
printf("%d\n",B);
return 0;
}
The compiler processes the #define-s in the order they were de...fined. After each #define gets processed, the preprocessor then proceeds to process all text after this #define, using it in the state left by this #define. So, in your example:
#define ONE 1
#define TWO (ONE+1)
It first processes #define ONE 1, replacing all further occurunces of ONE with 1. So, the second macro becomes
#define TWO (1+1)
That is how it will be processed and applied by the preprocessor.
The reverse example:
#define TWO (ONE+1)
#define ONE 1
will also work. Why? Well, the preprocessor will take the first #define, scan the code for any occurences of TWO, and replace it with (ONE+1). Then it reaches the second #define, and replaces all occurences of ONE, including those put in place by the previous #define, with 1.
I'd personally prefer the former approach over the latter: it's plainly easier for the preprocessor to handle.

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++

Why does my C program output this?

I am trying to solve two Preprocessor related questions but in both programs I am getting results that I am not able to figure out how. Below is my program:
#include<stdio.h>
#define SQUARE(x) x*x
int main()
{
float s=10,u=30 ,t=2,a;
a=2*(s-u*t)/SQUARE(t);
printf("Result:%f\n",a);
return 0;
}
According to me, the output of this programme should be -25.000 but I am getting -100.000.
And in second program:
#define FUN(i,j) i##j
int main()
{
int val1 = 10;
int val12 = 20;
clrscr();
printf("%d\n",FUN(val1,2));
getch();
}
Output should be 102 but I am getting 20;
why is it so?
#define SQUARE(x) x*x
should be
#define SQUARE(x) ((x)*(x))
Indeed, without the parentheses, 2*(s-u*t)/SQUARE(t) is expanded as
2*(s-u*t)/t*t
which is interpreted as
(2*(s-u*t)/t)*t
As to your second problem, FUN(val1,2) will get expanded as val12 per the semantics of the ## operator. It is still not clear what your intent is: the printf line will be understood as
printf("%d\n", val12);
which will print 20.
the first one:
a=2*(s-u*t)/SQUARE(t);
after replacing the define we get:
a=2*(s-u*t)/t*t;
now, since we don't have () in the definition of SQUARE we get:
a=2*(10-30*2)/2*2; --> a=2*(-50)/2*2; --> a=-100/2*2; --> a=-50*2; --> a=-100
if you want to get -25 you should define SQUARE(x) as (x*x).
Edit : add explanation regarding the second example.
printf("%d\n"FUN(val1,2));
once again, we first should replace the define (reminder: ## "concatenates" the string of the define - I can't find the perfect words in order to explain it so just take a look at the example...):
printf("%d\n",val12); [note: the comma (,) is missing - so it won't compile.]
since the value of val12 is 20 that's what you'll get.
the point of those 2 examples is to remember that we should always deal with the defines first (since in "real life" the compiler (or pre-processor) does it before the run time)
I hope it helps..
For the first case,
a=2*(s-u*t)/SQUARE(t);
would translate to
a=2*(s-u*t)/t*t;
at compile time. This is a common mistake made with preprocessors.
i know i am late, but i am having the perfect answer.
in c # at define is used to call the text as it is in the function parameter,
example, #define hai(s1) printf("%s=%s",#s1,s1);
in main: i am calling as hai(tom); tom was initialized as "india" string.
the output for this is tom=india, the calling string tom is printed by help of #.
similarly ## is used to take the text from function argument and join them and return the value of the joined identifier.
the above program has two argument va1 and 2. passed to i and j. then va1 and 2 is joined. and form va12.
va12 is the identifier available with value 20. that's why 20 is returned.

Resources