What is the difference between these two codes:
#define check 0
int main(void)
{
#if check
this is a normal line
#endif
return 0;
}
and this one:
int main(void)
{
/*
this is a normal line
*/
return 0;
}
Are they exactly the same ?
No they are not the same.
#define check 0
int main(void) {
#if check
this is a normal line
#endif
return 0;
}
This segment, when compiled, is completely dependent on the value of the preprocessed check value, currently at 0. Since the sole condition for compiling the code between your preprocessing if-endif is the 0|1 value of check, at runtime, they will be the same. However, if you were to change check to 1, it would compile the conditional line as well.
At compile-time, the first segment processes the #define check 0, where as the second, obviously, never has to and simply ignores the comment.
Yes, except that the first code won't compile for #define check ;-).
Related
Why the code inside the #ifdef INITIALISATION and #endif is not executed?
int main(void)
{
uint8_t DLEVEL = 10;
#if DLEVEL > 5
#define INITIALISATION
#endif
while (1)
{
#ifdef INITIALISATION
Display(); // This line is never being executing :: please help for a solution
#endif
}
}
edited...
Thanks for the reply
Actually the below mentioned logic of the code is used as a part of my code memory optimization.
Now the code memory size is overflowed, so i need to execute the one time initializations when the SYM_DLEVEL value is 10 and then the value of SYM_DLEVEL is changed from 10 to 2, then the initial sections i need to be automatically commented or disabled and then only the Display_2() function needed to be enable and need to execute.
Is it possible?
#define SYM_DLEVEL 10
int main(void)
{
#if SYM_DLEVEL > 5
Display_1(); // need to execute this line once(before the value changes from 10 t0 2)
#endif
#define SYM_DLEVEL 2 // after this line execution i need to automatically disable the above section and automatically enable the below section
#if SYM_DLEVEL < 5
#define INITIALISATION // need to execute only when value changes from 10 to 2
#endif
while (1)
{
#ifdef INITIALISATION
Display_2();
#endif
}
}
It doesn't execute code because the preprocessor runs in the compiler, while the local variable DLEVEL is assigned during execution.
The preprocessor simply looks for a preprocessor symbol DLEVEL that evidently is undefined.
Undefined symbols are equated to 0, so the symbol INITIALISATION isn't defined.
To make it work define a preprocessor symbol, i.e. SYM_DLEVEL, to be used in the conditional preprocessing, and eventually assign it to the runtime variable. I.e.
#define SYM_DLEVEL 10
int main(void)
{
uint8_t DLEVEL = SYM_DLEVEL;
#if SYM_DLEVEL > 5
#define INITIALISATION
#endif
while (1)
{
#ifdef INITIALISATION
Display(); // This line is now is executed
#endif
}
}
Remember that preprocessing is more or less a text processor (which actuates on base piece of text, tokens, as outlined in comments below), and is executed before the compilation of the code. It doesn't know about runtime variables and their assignments, it only knows symbols defined with a preprocessor directive (#define).
Don't confuse actions as dead code removal or other optimization made by compiler with what the preprocessor can do. The golden rule is: "preprocessing only understand preprocessing objects, C code is a plain text without any special meaning for it".
#define TEST
int i = 1;
int main(int argc, char const *argv[]) {
#if (defined(TEST) && i)
printf("it is printed");
#endif
return 0;
}
Do I have to create another macro for i?
If you want the output if and only if both the macro and the condition on the global variable are true then do like this:
#if (defined(TEST))
if (i)
{ printf("it is printed");
}
#endif
Reason (agreeing with comment by Barmar):
Preprocessor directives are evaluated at compile time, variables are not available at that time.
As in the comments, macro definitions are expanded during the preprocessing stage, before the actual C code compilation.
But why this code compiles and what will be the result of it.
#if (defined(TEST) && i)
preprocessor tests for macro definition TEST. As it was defined, the result of this check is true
now the preprocessor is checking if macro definition (not the C variable!) i exists. As it does not, the whole expression in the #if is evaluated to false.
Generally :
#if a
checks if macro definition a exists and then if its value is != 0,
Following program compiles successfully and print 1000 without even calling a foo() function from our main() function. How is it possible?
#include<stdio.h>
void foo()
{
#define ans 1000
}
int main() {
printf("%d", ans);
return 0;
}
#defineis run by the preprocessor which is staged before the compiler. After the preprocessor is done, the code will look like this:
/* Everything that is inside stdio.h is inserted here */
void foo()
{
}
int main() {
printf("%d", 1000);
return 0;
}
And this is what actually get compiled.
The preprocessor is very important to make header files work. In them, you see this structure:
#ifndef foo
#define foo
/* The content of the header file */
#endif
Without this, the compiler would complain if a header file is included more than once. You may ask why you would want to include a header file more than once. Well, header files can include other header files. Consider this macro, which is useful for debugging. It prints the name of the variable and then the value. Note that you would have to do a separate version for different types.
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
This is pretty versatile, so you may want to include it in a header file for own use. Since it requires stdio.h, we include it.
/* debug.h */
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
What happens when you include this file and also include stdio.h in you main program? Well, stdio.h will be included twice. That's why debug.h should look like this:
/* debug.h */
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
#define dbg_print_int(x) fprintf(stderr, "%s = %d", #x, x)
#endif
The file stdio.h has the same construct. The main thing here is that this is run before the compiler. The define is a simple replacement command. It does not know anything about scope or types. However, as you can see here, there is some basic logic built into it. Another thing that the preprocessor does is to remove all the comments.
You can read more about the C preprocessor here: http://www.tutorialspoint.com/cprogramming/c_preprocessors.htm
The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever [Ref: https://stackoverflow.com/a/36968600/5505997]. Clearly you do not need to call the function to set the value and obviously you will not get any error during compile.
As others have stated, #define is a preprocessor directive, not C source code. See Wiki here.
Point being, in your code #define ans 1000 is not a variable definition, meaning that even if you were calling foo() in the main, you would still not be setting "ans" at runtime, because it is simply not a variable. It is just telling the preprocessor what to do with the "label" "ans", when it finds it in your source code.
In this example, the main() will essentially be calling an empty foo() function:
int main()
{
foo(); // Calls an empty function
printf("%d", ans); // ans will have been substituted by 1000 by the time you start executing you code
return 0;
}
The definition of "ans" will simpy not exist anymore by the time you start executing you main(). This is what the preprocessor does (in part). It finds all the #defines declared in your entire source code and tries to find places in your code where you have used these defines. If you have not used them, it moves on (don't care), if you have, it substitutes the label by the actual defined value.
#include<stdio.h>
#define NUM 10
main()
{
#ifdef NUM
printf("compilation succesfull");
#endif
}
The above code compiles perfectly fine and upon execution prints
compilation successful, but if I remove a blank line before the first statement in main()
it gives an error. ie. "stray #" in the program and many other errors.
#include<stdio.h>
#define NUM 10
main()
{ #ifdef NUM
printf("compilation succesfull");
#endif
}
Can any one help me?
Preprocessor statements need to be on their own lines. So you can't put it on the same line as a { or anything else that's not part of the statement.
The preprocessor is unable to understand the line:
{ #ifdef NUM
The compiler doesn't know how to handle the statement #ifdef NUM, it'll say # is unknown and unknown type ifdef.
it'll reach the line
#endif
but didn't see ifdef before, thus you'll get #endif without #if error.
When you replace it in a new line, then the preprocessor knows what to do and the output will be:
main()
{
printf("compilation succesfull");
}
Validate this by running gcc -E yourprogram.
The Tag #ifdef you are using is correct. In the C language, lines that start with # in the code are called preprocessor directives. The preprocessor deletes them and uses them as commands to modify the code file prior to compilation.
For such statement for preprocessor, it should start in a new line, and only white space is allowed before the #. You should not put it after {.
For your code, compiler will like it, if it could be arranged as following.
#include<stdio.h>
#define NUM 10
main()
{
#ifdef NUM
printf("compilation succesfull");
#endif
}
I wish to add some conditional directive in my code to control different build, for example:
#if VERSION > 100
/* Compiling here */
#endif
The problem is that 'VERSION' is in other's code where I can't change. It was defined as a string:
#define VERSION "101"
I'm wondering if there's some sort of macro or directive which converts the string to number so I can simply do
#if STRING_TO_NUMBER(VERSION) > 100
/* Compiling here */
#endif
Is that possible please?
PS.
It seems my description is not quite clear. The main purpose of this requirement is to control the version branch. For example, in old version, pre-version 100, this program would like old_function(). After this version, all functions have been migrated to new_function. So I need to write codes like that:
#if VERSION >= 100
old_function();
#else
new_function();
#endif
#if VERSION >= 100
int old_function()
{
...
}
#else
int new_function()
{
...
}
#endif
You can see that only one of the function will be compiled. Therefore the condition must be decided in preprocessing stage, not in the runtime.
The tricky part is, the VERSION had been defined as a string, which brought this question.
If you need to interact with the pre-processor to set other #defines or conditionally #include different headers. Until you can get VERSION to be "fixed" to be an integer...
The only thing that I can think of for you to do is to create a tiny header file defining PROPER_VERSION and include it by naming each file as the version number. So here you would create:
100:
#define PROPER_VERSION 100
101:
#define PROPER_VERSION 101
102:
#define PROPER_VERSION 102
and then you would need to add the following:
#include VERSION
And then use PROPER_VERSION as you need
#if PROPER_VERSION > 100
...
Its not elegant, but I cannot see anything else you can do. You can auto-generate the VERSION file.
As long as you don't need to make declarations or preprocessor defines conditional on VERSION, and as long as you are confident that the VERSION string will just be an integer with no leading zeros, (both of which might be too much to ask for), you might be able to do this at compile time if your compiler has a reasonably effective constant expression evaluator.
For example, gcc 4.8 will optimize away the following if test, leaving only the appropriate arm:
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
} else {
// code if VERSION is "100" or less
}
The fact that only one of the branches of the if statement survives the compilation is easily demonstrated by inserting a call to an undefined function in the non-used branch. With gcc (and clang), and with optimization enabled, no linker error is produced:
#include <stdio.h>
#include <string.h>
#define VERSION "101"
// This function is not available for linking
int unknown_function();
// This one is in standard library
int rand();
int main(void) {
int x;
if (strlen(VERSION) > 3 || (strlen(VERSION) == 3 && strcmp(VERSION, "100") > 0)) {
// code if VERSION is at least "101"
x = rand();
} else {
// code if VERSION is "100" or less
x = unknown_function();
}
printf("%d\n", x);
return 0;
}
(See it at http://ideone.com/nGLGTH)
In C++11, there is an even more clearly compile-time version. You can create a constexpr version of atoi. Combined with what some might call an abuse of templates, that allows for conditional declarations:
constexpr int const_atoi(const char* num, int accum=0) {
return *num ? const_atoi(num+1, accum*10 + (*num - '0')) : accum;
}
template<bool V_GT_100> struct MoreOrLess_Impl;
template<> struct MoreOrLess_Impl<false> {
// Old prototype
void doit(double x) {...}
};
template<> struct MoreOrLess_Impl<true> {
// New prototype
void doit(long double x) {...}
};
using MoreOrLess = MoreOrLess_Impl<(const_atoi(VERSION) > 100)>;
// ...
// ... MoreOrLess::doit(x) ...
(Silly example at http://ideone.com/H1sdNg)