what do the # numbers in *.i files represent [duplicate] - c

This question already has answers here:
What is the meaning of lines starting with a hash sign and number like '# 1 "a.c"' in the gcc preprocessor output?
(3 answers)
cpp preprocessor output not able to understand? [duplicate]
(1 answer)
Closed 2 years ago.
I want know about the steps of execution of c program. I got this intermediate file which i can't understand
what are these numbers in the screenshot represent and what exactly that line it do.
# 1 "C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include/stdio.h" 1 3
# 9 "C:/Program Files (x86)/mingw-w64/i686-8.1.0-posix-dwarf-rt_v6-rev0/mingw32/i686-w64-mingw32/include/stdio.h" 3
take a look at ss

.i files are where gcc -save-temps outputs preprocessed C. This is C, not assembly language. You'll find asm in the .s file.
Those are line numbers to match up preprocessed C with the original source. I don't know exactly what the number at the start vs. the one or two numbers after the filename mean. If you need to know the details, you might need to look at GCC internals, or maybe it's documented somewhere.
With nested includes it can get fairly complex, but compilers can use this to print better warning messages (like where the original definition was of a conflicting prototype or something).
GCC has the C preprocessor built-in to the compiler pass so I'm not sure it actually needs to (or can) read these "comment" metadata lines in the .i; in normal operation the main C->asm compiler pass knows file/line-number of everything it read without having to serialize it into this text format and back.
GCC does have options to read preprocessed-C as input, specifically -fpreprocessed which is on by default if you were to run gcc -c foo.i.
Indicate to the preprocessor that the input file has already been preprocessed. This suppresses things like macro expansion, trigraph conversion, escaped newline splicing, and processing of most directives. The preprocessor still recognizes and removes comments, so that you can pass a file preprocessed with -C to the compiler without problems. In this mode the integrated preprocessor is little more than a tokenizer for the front ends.
-fpreprocessed is implicit if the input file has one of the extensions .i, .ii or .mi. These are the extensions that GCC uses for preprocessed files created by -save-temps.
So this is what lets GCC still remove those lines starting with # that are like preprocessor directives. (Like #define or #include).

Related

How to access all the files before compilation? [duplicate]

This question already has an answer here:
How do I save preprocessor output using the Dev-C++ IDE?
(1 answer)
Closed 2 years ago.
There are several steps involved from the stage of writing a C program to the stage of getting it executed.
when I compile the code I only get an .exe file. But I want to get all the files which are being made before the compilation (preprocess ones), an intermediate code file
where all those macros with are replaced with their actual values and preprocessor are replaced with their actual header files.
in general can we get all those files (preprocess one, compile one and linker one) separately?
To access all the intermediate files use the command (Ubuntu):
gcc –Wall –save-temps filename.c –o filename. This command generates all the intermediate files in current working directory.

C extra # lines after preprocessing part [duplicate]

I was inspecting the preprocessed output generated by GCC, and I see a lot of these in the .i file that I generated using the -save-temps flag:
# 8 "/usr/include/i386-linux-gnu/gnu/stubs.h" 2 3 4
What do the numbers before and after the absolute path of stubs.h mean? It seems to be some kind of debugging information that is inserted by the preprocessor and allows the compiler to issue error messages referring to this information. These lines do not affect the program itself, but what specifically is each number for?
Based on the documentation the number before the filename is the line number. The numbers after the file name are a flag and mean the following:
1 indicates the start of a new file.
2 indicates returning to a file (after having included another file).
3 indicates that the following text comes from a system header file, so certain warnings should be suppressed.
4 indicates that the following text should be treated as being wrapped in an implicit extern "C" block.

Including header files in C

I am working on a project in which If I could include a header file at runtime, it would save some programming effort. I google'd about it, but all in vain. My question is :
Can we include header files in a C program at runtime ?
If yes, how?
If not, why?
In C the source files are only read compile-time, so the answer to your question is not. Runtime there is only the executable binary, which has nothing to do with your source code headers.
Not really, no. Header files are brought in by the compiler to satisfy symbols needed during compilation.
If you simply want values unrelated to compilation, you can always put them in a configuration file which is read at runtime.
Other possible solutions are command line arguments or environment variables but, since you're discussing putting them into a file, the first option is probably the best.
No header files can't be added at run-time as,
The four stages for a C program to become an executable are the following:
1) Pre-processing
2) Compilation
3) Assembly
4) Linking
and Pre-processing is the very first stage through which a source code passes. In this stage the following tasks are done:
1) Macro substitution
2) Comments are stripped off
3) **Expansion of the included files**
and observation from intermediate file shows that we can get by passing argument to gcc as gcc -Wall -save-temps hello.c -o hello :
1) All the macros are expanded in the preprocessing stage.
2) All the comments are stripped off.
3) The third observation is that beside the line ‘#include’ is missing and instead of that we see whole lot of code in its place. So its safe to conclude that stdio.h and header files has been expanded and literally included in our source file.
and then compilation of code takes place ..
So including header files before compilation is needed.

How to invoke the C preprocessor?

How can we invoke the C preprocessor in a C program, like if we want to prepend some of our files to the list of standard library files while using #include<file_name> using -I, what we should do?
Adding, if we want to add comments to the output of our program, I have heard that we can use -C invocation commands. How to do it? Somebody please correct me and explain further if I am wrong.
The mechanism you linked to is explicitly not to be supposed from within a program, but it is to use the preprocessor for other things, like text libraries etc.
So you can transform a text using the means of the C preprocessor and convert it to its "expanded" form, without compiling it (perhaps it is a configuration file or whatever).
For example, you can have a
commonpart.h:
[General]
foo=1
bar=2
#define VALUE 3
and a
cfg.tmpl
#include "commonpart.h"
// This is a commet which won't show up in the end
baz=VALUE
you can do cpp -P cfg.tmpl and thus compile all this to
[General]
foo=1
bar=2
baz=3

Add compiler stage

I need to debug a C code with lots of macros, of which a bunch of them are not trivial at all and they include several (lots of) lines. That makes it impossible to debug, since macros are expanded in a single line and you never know where an error comes from. On the other hand, its easy with sed to take the preprocessor output and add lines after each semicolon.
I won't discuss about being a good practice to use macros such as these, because I can't do much about that. But I'd like to know whether I could add an stage to the compiler (I use several compilers:icc,gcc,xlc) between preprocessing and compiling, so it I rund that sed command.
What you can do is to run the pre-processor only (-E):
$ g++ -E in.c -o in.i
Then run your sed script and compile it's output with g++ (no -E this time). You could construct a rule for doing all this in your Makefile, I'm sure.
By now, I will try with what I found in this post. I also tried the option of the wrapper for compiling single files and, by the moment, it does the trick. In the wrapper, I preprocess (with -E) the file, I then process the preprocessed file with sed and some rules, and then I compile it.
Define your own "compiler" as a script to run g++ -E, then your sed-mangler, then g++, and specify that one as the compiler overall. Take care to use temporaries courtesy of mktemp, so starting your compiles in parallel (make -j) doesn't mess things up.
(Today's GCC doesn't have a separate preprocessing step anymore, so injecting something there can't be done easily anyway.)

Resources