Confusion about macro expansion in C - 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

Related

gcc preprocessor variables to string literals

I know there a bazillion question like this, but I couldn't find a good answer.
I'm compiling a source with preprocessor tokens defined in CFLAGS:
-D X=string1 -D Y=string2
I'm trying to create a string literal in my header file that combines these two values and use it in my sources like:
printf("%s", COMBINED);
But this doesn't work:
#define _COMBINED(x, y) x ## y
#define COMBINED _COMBINED(X, Y)
Thanks
To pass a string-ized token to a concatenating macro, you need a level of indirection. That means you pass it to a different macro.
#define COMBINED(a, b) (a##b)
#define COMBINE(a, b) COMBINED(a, b)
Then you pass off the params in COMBINE, in your case, X and Y
int main (void) // best practice is to void-erize non-param-ed functions
{
printf("%s\n", COMBINE(X,Y));
}
If you really want to do it "directly", you can do it like this:
#define DEFAULT_COMBINE COMBINE(X,Y)
And call:
printf("%s\n", DEFAULT_COMBINE);
Now, let's end with a caveat, as this is also about "best practice" so it's quite important even though it might not seem that way to you, it is, trust me on this one. Never ever, and i mean NEVER EVER start off your own preprocessor defines or constants with an underscore. Never, under any circumstances. Even if your brother works at Microsoft or worked on the Linux kernel.
In the standard and best-practice C and C++ world, the _COMBINED macro is illegal. No, not invalid, it just means you shouldn't name it like that. The short version is that constants, intrisincs and macros startign with an underscore are compiler or internal only. It's a "marker" to know that it's not something someone set.
UPDATE:
To concatenate them without being strings, you'll also need an intermediate step to stringify:
#define COMBINED(x1, x2) x1##x2
#define COMBINE_STRINGS(x1, x2) COMBINED(#x1,#x2)
#define COMBINE(x1, x2) COMBINE_STRINGS(x1, x2)
-D X=string1 creates a pre-processor token similar to #define X string1. Nothing so far makes this a string literal, you need to use the # "stringinizing" operator inside a function-like macro in order to do that.
Also when dealing with string literals there's no need to use token concatenation with ## since typing two string literals after each other means they get concatenated by the preprocessor.
As usual with # and ##, any macro argument that they are applied to needs to be expanded in advance before the operator is used, since these operators are always applied before token replacement. So we can't just do this:
#define STRCAT(x,y) #x #y
#define COMBINED STRCAT(X,Y)
// bad: result will BE "XY"
Instead use an additional helper macro:
#define STR(x) #x
#define STRCAT(x,y) STR(x) STR(y)
#define COMBINED STRCAT(X,Y)
// good: result will be "string1string2"
You did not show an example how you call the compiler, so I made some experiments. Since commas (and other non-alphanumerical characters) will get in the way, it boiled down to the need to pass quotation marks as delimiters of the replacement text of the macros.
So I think your real issue is how to pass the strings in an equivalent way to:
#define X "hello, "
#define Y "world!"
Note: Here extra difficult because of comma and exclamation mark.
If the macro replacement text is passed including the quotation marks, the C source gets simple. In C, you concatenate string without any intermediate operator. "abc" "def" is the same as "abcdef".
#include <stdio.h>
#define COMBINED X Y
int main(void) {
printf("%s\n", COMBINED);
}
Depending on your real use case, you could even simplify this to:
#include <stdio.h>
int main(void) {
printf("%s\n", X Y);
}
In a Bash you need to escape the command line arguments like this, for example:
gcc -Wall -pedantic -D 'X="hello, "' -D 'Y="world!"' combine.c -s -O3 -o combine
In Windows' CMD you can escape the quotation marks like this, for example:
gcc -Wall -pedantic -D "X=\"hello, \"" -D "Y=\"world!\"" combine.c -s -O3 -o combine.exe

How to pass value in #define directives in c?

I want to pass value in #define directives. I am new to c programming. For example we use %s or % d in printf function printf("hello %d",into); how can I use same in # define directives.my code is #define URL "www.my website.com" I am trying to pass value using following code #define URL "my website.com%d", int but I am getting no result
You can use Macro arguments:
#include <stdio.h>
#define URL(i) "www.mywebsite.com"#i
int main() {
printf(URL(5)); // Will print www.mywebsite.com5
return 0;
}
# is called the pasting operator. It pastes two tokens together.
OR you can do this...
#include <stdio.h>
#define URL(i) "www.mywebsite.com %d", i
int main() {
printf(URL(5));
return 0;
}
Difference:
In the 1st solution, the pre-processor simply pastes any value of i with "www.mywebsite.com". It doesn't necessarily have to be data. It can be anything.
If you pass in URL(ABC) (Note: ABC is not a string. It is without quotes. It is just a simple token.), your output will be www.mywebsite.comABC.
If you pass in URL("ABC") ("ABC" with quotes), you output will be www.mywebsite.com"ABC".
So in short, it doesn't matter what you pass, pre-processor doesn't care about the data-type. It treats it just as a simple token and pastes it with www.mywebsite.com. Here your "ABC" wasn't treated as a String by pre-processor but as any other token.
In the 2nd solution, the pre-processor doesn't do any pasting. It simply evaluates your printf statement as, printf("www.mywebsite.com%d", i). So you will need to pass in an integer as URL(5) or any other integer apart from 5. If you pass data of any other datatype, it will give you a warning. You can't pass URL(ABC). It will give an error. Because ABC is not data. But if you pass "ABC" as a string(i.e, with quotes), it will give a warning but your code will compile and result output would be www.mywebsite.com96882598

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 as an argument to a macro in C

I want to know which macro gets replaced first in the following code
#define A 100
#define B 200
#define C(A,B) A+B
here when we use C, then evaluation will be from left to right or right to left. That is B gets the value first or A gets the value first
i gave this example just to make things look simple, may be i was wrong. the actual thing i want to ask is, if A and B also take arguments and have the scope of expansion, then which one would expand first
I'm not sure what you mean. There's never a point where you can "see" half a result of the preprocessor; the entire input file is preprocessed, then handed over to the compiler.
I think that the names for the macro arguments will never also be replaced as if they were stand-alone symbols.
I tried it, and this program:
#include <stdio.h>
#define A 100
#define B 200
#define C(A, B) A + B
int main(void) {
printf("A=%d\nB=%d\nC(1,2)=%d\n", A, B, C(1,2));
return 0;
}
prints
A=100
B=200
C(1,2)=3
So, C(1,2) expands to 1 + 2, the definitions of A and B don't matter.
Of course I must say that I find the above very bad practice, since it's quite confusing. Never use all-caps names for macro arguments, since macros and preprocessor symbols tend to use such names.

How to write C program without 'main'?

How to write C program without using Main...!
When I'm learning how to write ASM file by for a simple C file [of length 3 lines], I got this doubt.
I assembly file I used preamble and post ambles, at function.
There is a great article and creating the smalest possible elf binary here. It has a lot of info of what is required to have something runnable by the os.
This is logical trick. Those who are unaware of it, can learn this trick.
#include<stdio.h>
#include<conio.h>
#define decode(s,t,u,m,p,e,d) m##s##u##t
#define begin decode(a,n,i,m,a,t,e)
void begin()
{
clrscr();
printf("\nHello !!! Kaushal Patel.");
getch();
}
Explanation :
The
pre-processor directive #define with arguments is used to give an impression
that the program runs without main(). But in reality it runs with a
hidden main().
The ‘##‘
operator is called the token pasting or token merging operator. That is
how, I can merge two or more characters with it.
#define decode(s,t,u,m,p,e,d) m##s##u##t
The macro
decode(s,t,u,m,p,e,d) is being expanded as “msut” (The ## operator
merges m,s,u & t into msut). The logic is when I pass
(s,t,u,m,p,e,d) as argument it merges the 4th,1st,3rd & the 2nd
characters.
#define begin decode(a,n,i,m,a,t,e)
Here the
pre-processor replaces the macro “begin” with the expansion
decode(a,n,i,m,a,t,e). According to the macro definition in the previous
line the argument must be expanded so that the 4th, 1st, 3rd & the
2nd characters must be merged. In the argument (a,n,i,m,a,t,e)
4th,1st,3rd & the 2nd characters are ‘m’,’a’,’i’ & ‘n’.
So the third line “void begin” is replaced by “void main” by the pre-processor before the program is passed on for the compiler.
Source :
http://ctechnotips.blogspot.in/2012/04/writing-c-c-program-without-main.html
Here is your answer:->
#include <stdio.h>
extern void _exit(register int);
int _start(){
printf(“Hello World\n”);
_exit(0);
}

Resources