I know that probably there is no concept of scope for macros, but please help me understand the following output - which seems to suggest that macros are local to functions:
#include<stdio.h>
#include<stdlib.h>
#define A 100
void fun();
int main()
{
fun();
printf("%d\n",A);
system("pause");
return 0;
}
void fun()
{
#undef A
}
The output of the program is 100 though according to me it should have been a compiler error. Please explain why?
The pre-processor works on the text of your source code and it does it before the compiler proper ever starts to run.
In essence your compiler works on a file that looks like
/* Lots of code from the included files omitted */
void fun();
int main()
{
fun();
printf("%d\n",100);
system("pause");
return 0;
}
void fun()
{
}
So running and printing 100 is exactly what you would expect.
Notice that all the pre-processor directives are gone, and that all instances of A between the define and the undef have been replaced with 100.
The thing to remember is:
The pre-processor runs, changing the text
Then the compiler runs on the result
The preprocessor makes a single pass though the program text at compile time. By the time the program runs all of the directives are long gone.
Originally, the preprocessor was actually a separate program that understood C only to the extent that it parsed tokens the same way. After creating a macro-expanded version of the program as a temporary file, the real compiler was run. Today, it's integrated into the compiler, but in such a way that the effect is the same.
This is how the convention of using all-upper-case macro names began, i.e., in order to emphasize their substantially different nature. You can still get the compiler to output the expanded-but-uncompiled intermediate text. This is occasionally useful when tracking down bugs and understanding complicated conditional compilation.
You can't run preprocessor commands in functions. They're removed from compiled code. That's why they're called preprocessor: they are executed and removed before the program is compiled. In fun(), you are undefining the number 100.
Macros are executed at compile time (in fact before the compiler).
macro expansion is done at preprocessing step, which is a step before compiling.
If you like to see how the code looks after this step, try compile with preprocessing only option.
e.g.
gcc -E myfile.c > myfile.ppout
and read the output.
Related
For a large software developed by C, we first declare all the self-defined functions in a separate header file (e.g. myfun.h). After that, once we write a code (e.g. main.c) that uses the functions listed in myfun.h, we have to #include "myfun.h". I'm wondering how it works, because even if I include the function names declared in header file before the main body, the code cannot see the function details in main.c. I guess it will search the library to get the function details...Am I right?
When you say "it will search the library for the function details" you're not far off, but that isn't quite right. A function declaration, i.e.. a function prototype only contains enough information for the compiler to do two things:
First, the compiler will register the function as a known identifier so that it knows what you're taking about when you call it, as opposed to a random string of letters with parentheses (to the compiler, they are essentially the same thing without a function prototype for either - an error).
Second, the compiler uses the function prototype for checking code correctness. Correctness in this sense means that a function call will match the prototype in both arity and type. In other words a function call to int square(int a, int b); will have two arguments, both integers.
The program doesn't "search the library," though. Function names without parentheses are not function calls but rather function's address. Therefore, when you call a function, the processor jumps to the memory location of the function. (This assumes the function has not been inlined.)
Where is this function located though? It depends. If you wrote the function in the same module, i.e... a .c file that got compiled into an object linked with the main.c file into a single executable, then the location of the function will be somewhere in the .TEXT section of the executable. In other words, it's just a slight offset from the main function's entry point. In a huge project this offset won't be so slight, but it will be shorter than the offset of separate objects.
Having said that, if you compiled this hypothetical function into a DLL which you call from your main program, then the function's address will be determined in one of two ways:
Either you will have generated a .lib/.a? (depending on whether you're on Windows or Linux) file containing the function declaration's and addresses, or:
You will use run-time linking where the main program will calculate the function addresses when it loads the .dll/.so into its address space. First, it will determine where to load it. You can set DLL's to have preferred offsets to optimize load time. Otherwise, libraries will start loading from the first segment available and any additional libraries will need their function address recalculated using this new address, hampering initial load times. Once they are loaded into the program's memory though, there shouldn't be any performance hits thereafter.
Going back to the preprocessor, it's important to note two things. First, it runs before any compilation takes place. This is important. Since the program is not really being "compiled" when the preprocessor is doing its thing, macros are not type-safe. (Insert Haskell joke about C "type safety") This is why you don't -or shouldn't- see macros in C++. Anything that can be accomplished with macros in C can be accomplished by const and inline functions in C++, with the added benefit of type safety.
Second, the preprocessor is almost just a search and replace engine. For example, in the following code, nothing happens because the preprocessor if statement evaluates to false, since I never defined anything. The preprocessor removes the code in this section. Remember that since the compiler has not run in earnest yet, this removed code will not be compiled. This fact is usually utilized to implement functions for debugging or logging in debug builds. In release builds the preprocessor definition is then manipulated such that the debug code is not included.
#include <stdio.h>
#include <stdlib.h>
int main()
{
#if TRUE
printf("Hello, World!");
#endif
return EXIT_SUCCESS;
}
In fact, the EXIT_SUCCESS macro I used is defined in stdlib.h, and replaced by 0. (EXIT_FAILURE =1).
Back in the day, the preprocessor was used as duct tape, basically, to compensate for faults in C.
For example, since const values can't be used as array sizes, macros were used instead, like this:
// Not valid C89, possibly even C99
const int DEFAULT_BUFFER_SIZE = 128;
char user_input[DEFAULT_BUFFER_SIZE];
// Legal since the dawn of time
#define DEFAULT_BUFFER_SIZE 128
char user_input[DEFAULT_BUFFER_SIZE];
Another significant use of the preprocessor was for code portability, for example:
#ifdef WIN32
// Do windows things
#elif
// Handle other OS
#endif
One trick was to define a generic function and set it to the appropriate OS-dependent one (Remember that functions without the parentheses represent the function's address, not an actual function call), like this:
void RequestSomeKernelAction();
#ifdef WIN32
RequestSomeKernelAction = WindowsVersion;
#else
RequestSomeKernelAction = OtherOSFunction;
#endif
This is all to say that the code you see in header files follows these same rules. If I have the following header file:
#ifndef SRC_INCLUDES_TEST_H
#define SRC_INCLUDES_TEST_H
int square(int a);
#endif /** SRC_INCLUDES_TEST_H */
And I have this main.c file:
#define SRC_INCLUDES_TEST_H
#include "test.h"
int main()
{
int n = square(4);
}
This program will not compile. The square function will not be known to main.c because while I did include the header file where square is declared, my #define SRC_INCLUDES_TEST_H statement tells the preprocessor to copy all the header file contents over to main except those in the block where SRC_INCLUDES_TEST_H is defined, i.e... nothing.
These preprocessor commands can be nested, and there are several, which I highly recommend you look up, if only for historical or pedagogical reasons.
The last point I will make is that while the C preprocessor has its faults, it was a powerful tool in the right hands, and in fact, the first C++ compiler Bjarne Stroustroup wrote was essentially just a preprocessor.
I am using Gnu cc compiler of Gcc to compile my C programs. Consider a program,
#include <stdio.h>
int main(){
return 0;
}
Now, when I pre-process the above code, using
cpp sample.c > sample.i
I get a lot of contents in sample.i which I haven't included. Say, 'stdio.h' file is preprocessed. If that is the case,
Question 1:
Why are there so many lines in my preprocessed file? I haven't used any of the standard library functions nor Macros.
Question 2:
Can anyone explain what exactly happens when the preprocessor proccess the C file.(The contents that I got in my '*.i' file)
Compiler: gcc
OS: Ubuntu
Thanks
Why are there so many lines in my preprocessed file? I haven't used any of the standard library functions nor Macros.
Preprocessing is just one part of the compilation process. It's more or less a simple textual replacement and nothing more complex is involved at the preprocessing stage. The preprocessor does not know or care whether you have used any standard functions in your code program or not. An optimizer (as part of the compilation process) might
"remove" parts that are not needed. But the preprocessor doesn't do that.
It'll do preprocessing of all the header files you have included and other header files included via your header files and so on.
Can anyone explain what exactly happens when the preprocessor process the C file.(The contents that I got in my '*.i' file)
The preprocessing involves quite a few tasks: macro replacement, conditional compilation, stringification, string concatenation etc.
You can read more about cpp in detail here: https://gcc.gnu.org/onlinedocs/cpp/
the preprocessor command #include "aFile.h" will put the hole content from aFile.h into your cpp file. And that exactly to the place, where the preprocessor directives stands. That is the reason why you can use the in aFile.h defined functions.
if you are interest to learn more about the preprocessor, there is a very good (and short) guidance on cplusplus.com
The preprocessor does text substitution. The net effect of #include <stdio.h> is to replace the #include <stdio.h> line with the contents of <stdio.h>.
Practically, <stdio.h> contains several declarations of various functions (e.g. fprintf(), fscanf()), declarations of variables (e.g. stdout, stdin), and some macro definitions (which, when used in later code, cause text substitution).
The preprocessor is specified as a phase of compilation, which takes source code as input, substitutes text as required (e.g. the #include as I have described, macro expansions, etc), and outputs the resultant source code. That output is what you are directing into sample.i
The output of the preprocessor is then input to a later phase of compilation, which actually understands declarations, definitions, statements, etc.
The phases of compilation are sequential - they occur one after the other, not all at once. So the later phase of compilation feeds no information whatsoever back to the preprocessor. It is the later phase of compilation that detects if declarations etc are used. But, since it cannot feed such information back to the preprocessor (and the preprocessor is an ignorant program that couldn't use such information anyway) the preprocessor cannot know that declarations are unused, and filter them out.
1) You may not use them, but you have included them in line 1
#include <stdio.h>
That's where what you see come from. Try to remove it to see the difference.
2) The preprocessor read your C file and processed all preprocessor directives that you have declared. All Preprocessor directives start with a '#' symbol. The '#include' will replace this line by the content of the given file. You also have the classical '#ifndef' and '#define' directive. The latter is equal to 'if' statement which allow you to activate a part of a code only if a symbol is defined
#ifndef _SOME_SYMBOL_
#define _SOME_SYMBOL_
#ifndef WIN32
#include <some_file.h>
#else
#include <some_other_file.h>
#endif
int main() { return 0;}
#endif //endof _SOME_SYMBOL_
#ifndef _SOME_SYMBOL_
#define _SOME_SYMBOL_
// this second function is ignored
int main() { return 0;}
#endif //endof _SOME_SYMBOL_
When the preprocessor reads the above file, the symbol "_SOME_SYMBOL_" is unknown, so the preprocessor initializes it. Next it includes the file whether or not it knows of WIN32. Usually this kind of symbol is passed trough command line. So part of your code is dynamically activated or deactivated.
The preprocessor will output this
void some_other_function_from_some_other_file(){}
int main() { return 0;}
I am trying to understand the idea of function like Macros however there are a few points that befuddle me. For example say we have:
#define Max(a,b) ((a)>(b)) ? (a):(b))
and I call it like such
int i = Max(4,5);
This will evaluate a conditional expression equivalent to a>b? If yes then a, else b. But I'm confused as to how the Max function knows what to do with the arguments. Unlike an actual function, the implementation isn't written in code in the calling program. is the statement to the right of the define statement doing this for me? Its just a new thing for me and I want to make sure I understand what is happening here.
This particular part of function like macros confuses me. I know that these types of macros are useful for reducing overhead costs since they exclude the JSR RTS processor instructions which saves memory on the stack.
#define Max(a,b) ((a)>(b)) ? (a):(b))
is a macro, that causes nothing else but a simple textual replacement within your code, which means that during the preprocessing this line:
int i = Max(4,5);
is changed into:
int i = ((4)>(5)) ? (4):(5));
Note that there is no type safety while working with macros like this one and you will have really hard time while debugging your code as well. Good rule of thumb is: Don't use macro when you can achieve the same with function:
int max(int a, int b) {
return (a > b) ? a : b;
}
What the compiler actually sees, after preprocessing, is:
int i = ((4)>(5)) ? (4):(5));
The parameters passed to the macro are substituted into the body of the macro.
Just stop thinking about macro like compilable code. Macros are "resolved" by pre-processor, not actually during compilation stage. So by macro definitions you just define how to process certain string in text file. Only output of pre-processor is passed to compiler. You can use gcc -E to see your source after pre-processor. It is still C code on this stage but without any preprocessor directive.
Hope this will help you.
try to build your code with the gcc -E and see how your code look before compiling it
In fact in the build process the compilator transform your actual code to a preprocessor code.
In the preprocessor phase the compilator replace all macro in your c code with its content and generate another code called preprocessor code and then the compilateor generate the object code from the preprocessor code
The gcc -E allow you to see your preprocessor code
I went through all sorts of quine problems, but my task was to get a quine problem without main(), and loops are also forbidden.
Without loop, it is easy, but I can't figure out how to write one without main(). Can anyone help me or provide me with a link?
You cannot create a (non-freestanding) C program without a main() function. Thus, creating a quine in C without a main() is impossible in the usual sense.
That said, depending on how you define a quine, you might be able to construct a source file which fails to compile, but for which the compile error (on a certain specific compiler) is the contents of the source file.
First thing its impossible to write program without main function because compiler always starts execution from main() function, without main function linker will not be aware of start of data segment.
Yeah but playing with some tricks with preprocessor you can do it, but this is not a good method to do that.
http://www.gohacking.com/2008/03/c-program-without-main-function.html
This might help you.
Take a look here too:
Is a main() required for a C program?
#include <stdio.h>
int
foo(void) {
printf("pong!\n");
return 0;
}
int main() __attribute__((weak, alias("foo")));
There is main() declaration, but not definition.
I added this in my code:
#ifdef DEBUG_MODE
printf("i=%d\n",i);
fflush(stdout);
#endif
and my question is, if I'm not in DEBUG_MODE what the compiler does when compiling this?
The compiler will do nothing, because there will be nothing there when DEBUG_MODE is not defined.
#ifdef and #endif control conditional compilation. This happens during an initial pass over the program, making dumb textual substitutions before the compiler even begins to consider the file to contain C code specifically. In this case, without the symbol defined only whitespace is left. The text is never even lexed into C tokens if the preprocessor define tested for isn't defined at that point.
You can see this for yourself: just invoke your compiler with whatever flag it uses to stop after preprocessing - e.g. gcc -E x.cc - and at that point in the output there will just be an empty line or two. This is also a very important technique for understanding macros, and a good thing to do when you just can't guess why some program's not working the way you expect - the compiler says some class or function doesn't exist and you've included its header - look at the preprocessed output to know what your compiler is really dealing with.
if DEBUG_MODE is not defined, the code under it will not be compiled.