Which result does return this construct? I mean the result variable in main-function, and why?
I know, that the example is very strange ;)
header1.h file:
extern const int clf_1;
header2.c file:
#include "header1.h"
const int clf_1 = 2;
test.h file:
#include <header1.h>
#define xyz clf_1
#define NC_CON 2
#if (xyz== NC_CON)
#define test 40
#else
#define test 41
#endif
C file
#include <header1.h>
#include <test.h>
int main(int argc,char *argv[])
{
int result = 0:
if (test == 40)
{
result = 40;
}
}
Read the wikipage on the C preprocessor and the documentation of GNU cpp (the preprocessor inside GCC, i.e run by gcc or g++ etc...). It is a textual thing, and it is run before the definition const int clf_1 = 2; has been processed by the compiler. A #if directive only makes sense if all the names appearing in it are preprocessor symbols (defined with #define or with -D passed on the command line of the GCC or Clang/LLVM compiler)
Use gcc -C -E yoursource.c > yoursource.i (with some other options after gcc, probably -I. is needed ... you should #include "header1.h"
etc...) then look with an editor or a pager into the generated yoursource.i (the preprocessed form)
The world would be very different if the C preprocessor transformed ASTs; for historical reasons, the first C preprocessors were textual filters (run as a different program).
Related
I'm unsure of the terminology, but I would like to know if in the following scenario, main.c has access to x.cs #defines:
/*x.h*/
#define ONE 1
/*x.c*/
#include "x.h"
#define TWO 2
/*main.c*/
#include "x.h"
int a = ONE;
int b = TWO;
You could just tell me to run gcc -o out main.c x.c if I want to know. But it might work, yet not be correct. This is why I am asking you. My goal is to have the #defines in x.c be local to that file, so they don't clash with any others in main.c. On the other hand, I do want #defines from x.h to be available to main.c because they need to be used when implementing the functions from x.c
Please advise
Your two .c files are equivalent to the following:
x.c :
#define ONE 1
#define TWO 2
main.c :
#define ONE 1
int a = ONE;
int b = TWO;
Any #define in a .c file will be local to that file. This is a common practice when optimizing code, leave a #define that is exclusively used in a .c file declared in that same c file.
Edit : BUT as #defines and #includes (and many other preprocessor directives) are expanded, this is done from top to bottom. meaning that one directive can then recieve #defines from some #include that was expanded earlier.
Here's an example of what I'm saying:
a.h :
#define A 1
b.h :
#define NEW_A A+1
main.c :
#include "a.h"
#include "b.h"
#include <stdio.h>
int main() {
printf("%i, %i\n", A, NEW_A);
return 0;
}
Will output:
1, 2
I'd suggest reading about compilation units and preprocessor directives in C.
so i create the object files with
cc -c MAIN.C
cc -c tablero.c
but then when i try to link them to an executable with
cc MAIN.o tablero.o
i get
undefined reference to `asdf()'
(function defined in tablero.c and called in MAIN.C)
here are my files:
i have MAIN.C
#include <stdio.h>
#include <cstring>
#include "tablero.h"
int main()
{
int c;
printf( "Enter a value :");
c = getchar( );
putchar(c);
printf( "\nYou entered: ");
c = asdf ();
putchar(c);
return 0;
}
i have tablero.h
#ifndef TABLERO_H_
#define TABLERO_H_
int asdf();
#endif // TABLERO_H_
and i have tablero.c
#include "tablero.h"
int asdf() {return 48;}; //48 is 0 in ascii
You have been bitten by an obscure feature of the cc tool on many Unixy systems: files whose suffix is lowercase .c are compiled as C, but files whose suffix is uppercase .C are compiled as C++! Therefore, your main (compiled as C++) contains an external reference to a mangled function name, asdf() (aka _Z4asdfv), but tablero.o (compiled as C) defines only an unmangled name, asdf.
This is also why you were able to include the C++ header file <cstring> in what was meant to be a C program.
Rename MAIN.C to main.c (and change <cstring> to <string.h>), recompile main.o, and your program should link.
If you actually want to compile part of your program as C and part as C++, then you can annotate your header files with extern "C" to make the symbols match up:
#ifndef TABLERO_H_
#define TABLERO_H_
#ifdef __cplusplus
extern "C" {
#endif
int asdf(void);
#ifdef __cplusplus
}
#endif
#endif // TABLERO_H_
Header files like this have to be extra careful to contain only code that has the same meaning in C and C++. Only POD types, no C++ keywords, no C99-but-not-C++ keywords either, no overloads, et cetera.
I would like to specify the name of a C include file at compile time as a C flag.
e.g.
#include MY_INCLUDE_FILE
int main(int argc, const char * argv[]) {...}
Would be expaned by the pre-processor to
#include "some_incfile.h"
int main(int argc, const char * argv[]) {...}
Doing something like this
gcc -DMY_INCLUDE_FILE="some_incfile.h" main.c
I have attempted using the stringizing operator # to expand but have only gotten errors such as error: expected "FILENAME" or <FILENAME>
Is this even possible?
-D define is not entirely necessary, the important part is that the include filename can be set from the gcc command line
You have to escape the ":
gcc -DMY_INCLUDE_FILE=\"some_incfile.h\" main.c
Use the -include option.
gcc -include "somefile.h" main.c
You can do it something like that
# if defined AAA
#define INC "x.h"
#elif defined BBB
#define INC "y.h"
#endif
#include INC
and from command line you do gcc -DAAA.
and of course, you can pass directly gcc -DINC="\"FILE.h\"" if the file is really randomly generated from outside, by makefiles, etc.
Important is INC to be evaluated to a valid file name by the macro expansion procedure (see the Prosser's algorithm).
I've added a bunch of "debug(x)" statements to my code using preprocessing macros in a header file. I've also implemented a toggle (via an #ifdef / #else structure in the header file) that lets me turn off the debug statements. I'm having trouble getting this toggle to work and am hoping someone can figure out the reason.
Rather than re-posting the actual code (which is lengthy), I'm including an illustrative example (which does compile).
Here's our .h file. It consists of a macro for a function named "superman". The statement should print if and only if KRYPTONITE is not defined in our .c file.
test.h:
#ifndef __test_h__
#define __test_h__
#ifdef KRYPTONITE
#define superman(...)
#else
#define superman(xs) printf("%s\n\n",xs)
#endif
#endif
As you can see in the cases below, adding a "#define KRYPTONITE 1" statement to the beginning of our .c file does not toggle off the "superman" function (Case 2 below). However, we do successfully toggle off if we define KRYPTONITE via a flag in our compile instruction (Case 3).
What else do I need to do in order to toggle off the "superman" function via a "#define" statement in the .c file?
Case 1: KRYPTONITE not defined in the .c file (it's commented out). As expected, the statement prints. (The .c file and output is below.)
test1.c:
#include <stdio.h>
#include "test.h"
//#define KRYPTONITE
int main (int argc, char *argv[])
{
printf("\nSuperman, are you here?\n\n");
superman("I'm here");
return 0;
}
Output:
dchaudh#dchaudhUbuntu:~/SO$ gcc test1.c -o test1
dchaudh#dchaudhUbuntu:~/SO$ ./test1
Superman, are you here?
I'm here
dchaudh#dchaudhUbuntu:~/SO$
Case 2: KRYPTONITE is defined in our .c file, yet the statement prints.
test2.c:
#include <stdio.h>
#include "test.h"
#define KRYPTONITE
int main (int argc, char *argv[])
{
printf("\nSuperman, are you here?\n\n");
superman("I'm here");
return 0;
}
Output:
dchaudh#dchaudhUbuntu:~/SO$ gcc test2.c -o test2
dchaudh#dchaudhUbuntu:~/SO$ ./test2
Superman, are you here?
I'm here
dchaudh#dchaudhUbuntu:~/SO$
Case 3: KRYPTONITE is not defined in our .c file but we define it via a flag when compiling. In this case, the superman function is successfully toggled off.
Output:
dchaudh#dchaudhUbuntu:~/SO$ gcc -DKRYPTONITE test1.c -o test3
dchaudh#dchaudhUbuntu:~/SO$ ./test3
Superman, are you here?
dchaudh#dchaudhUbuntu:~/SO$
The proeprocessor, just like the C compiler, scans files from top to bottom. That means macros must be defined before they are used.
So to solve your problem, put the #define before the #include.
#include <stdio.h>
#define KRYPTONITE
#include "test.h"
int main (int argc, char *argv[])
{
printf("\nSuperman, are you here?\n\n");
superman("I'm here"); // Doesn't print
return 0;
}
I need to expand a single preprocessor directive, for example:
Having a source file and two headers, I want to expand only one define from one specific header, leaving all other include and define intact.
The main idea is that, given code similar to this:
defs.h:
#define FOO(X,op) int X(int a,int b) { return a op b; }
other_file.h:
#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4
#define FIVE 5
main.c:
"file: main.c "
#include <stdio.h>
#include "defs.h"
#include "other_file.h"
FOO(add,+)
FOO(sub,-)
FOO(mul,*)
FOO(div,/)
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
I would have the main.c output with the same includes, but with FOO expanded to the created functions. I known the example is silly, but I intend to run it on a larger code database.
The motivation to do it is to run cccc in functions that are defined within macros. The easiest way to run it is to expand those macros. I also welcome alternative ways to do this.
You can play with the -E, -nostdinc, -nostdinc++ and -fpreprocessed parameters of GCC.
For your example, you can run:
gcc -E -nostdinc -fpreprocessed main.c
And the output would be:
# 1 "main.c"
#include <stdio.h>
#include "defs.h"
#include "other_file.h"
FOO(add,+)
FOO(sub,-)
FOO(mul,*)
FOO(div,/)
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
If the headers are not that complex, like in your example, you can force gcc to preprocess the whole file even with some missing macros. E.g.:
cp other_file.h other_file.h_orig
echo "" > other_file.h
gcc -E -nostdinc main.c
Output:
# 1 "main.c"
# 1 "<command-line>"
# 1 "main.c"
main.c:1:19: error: no include path in which to search for stdio.h
#include <stdio.h>
^
# 1 "defs.h" 1
# 3 "main.c" 2
# 1 "other_file.h" 1
# 4 "main.c" 2
int add(int a,int b) { return a + b; }
int sub(int a,int b) { return a - b; }
int mul(int a,int b) { return a * b; }
int div(int a,int b) { return a / b; }
int main()
{
printf("%d\n",add(ONE,TWO));
printf("%d\n",sub(THREE,FOUR));
printf("%d\n",mul(FIVE,FIVE));
printf("%d\n",div(25,FIVE));
return 0;
}
It will remove the header inclusions, though... and will print you an error on std headers, that goes to stderr instead of stdout.
This works for your small example, but on larger codebase you may face some problems...
Here is a brief summary of the parameters from the manual (of GCC 4.8.2) :
-E: Stop after the preprocessing stage; do not run the compiler proper. The output is in the form of preprocessed source code, which
is sent to the standard output.
-fpreprocessed: 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.
-nostdinc: Do not search the standard system directories for header files. Only the directories you have specified with -I options.
-nostdinc++: Do not search for header files in the standard directories specific to C++, but do still search the other standard
directories.
Our DMS Software Reengineering Toolkit with its C Front End will do this.
DMS provides general purpose program parsing/analysis infrastructure. The C Front End builds on that to provide a full-function C front, complete with C preprocessor.
Normally, the DMS C preprocessor acts just like the standard one: it preprocesses everything, producing a substituted stream of tokens. Unusually, it can be configured to NOT process conditionals (this is all-or-nothing), or to expand only designated macros. In particular, it accepts a custom #pragma that declares that a macro should (not) expand.
It isn't clear to me that this is worth the effort. Yes, a metrics tool might produce more accurate answers in certain places where some macro is heavily used, if you believe that the macro should be non-opaque. If you think the macro is essentially just a funny-looking subroutine, then expanding this macro is like inlining a function body, and you would not do that to compute metrics.