In ruby there's very common idiom to check if current file is "main" file:
if __FILE__ == $0
# do something here (usually run unit tests)
end
I'd like to do somet开发者_Go百科hing similar in C after reading gcc documentation I've figured that it should work like this:
#if __FILE__ == __BASE_FILE__
// Do stuff
#endif
the only problem is after I try this:
$ gcc src/bitmap_index.c -std=c99 -lm && ./a.out
src/bitmap_index.c:173:1: error: token ""src/bitmap_index.c"" is not valid in preprocessor expressions
Am I using #if wrong?
As summary for future guests:
- You cannot compare string using #if
- BASE_FILE is the name of file that is being compiled (that Is actually what I wanted).
- Best way to do this is to set flag during compilation with -D
in gcc you can use:
#if __INCLUDE_LEVEL__ == 0
or:
if(!__INCLUDE_LEVEL__)
to check if your inside the __BASE_FILE__
Yes, you are misusing #if
. It only works on integer constant expressions. But even if you were using if
, comparing pointers for equality is never a valid way to compare strings in C.
It seems you can't.
Alternatively, it works perfectly fine on a regular if condition, and gcc can optimize this nicely.
if (!strcmp(__BASE_FILE__, __FILE__)) {
// works.
}
but you can't define new main functions or use other preprocessor tricks. but you could short-circuit main by using static methods, but that's harsh and dirty.
But maybe you shouldn't do it. in Ruby/python, this works because usage of files is done at runtime. in C, all files are to be compiled to be used.
Keep in mind that most build system will build one file at a time, building them as object files, and rebuilding them only when necessary. So
__BASE_FILE__ and __FILE__
will be equals most of the time in sources files, if not always. And i would strongly discourage you to do this in header files.
It's easier to just put your tests in separate files, only linking them when needed.
Yup, as others say, you're misusing it since you can't compare strings that way in C, and especially not in the preprocessor.
The file that defines int main(int argc, char* argv[])
is the main file. There can be only one such function in an executable.
In addition to what others have said (you can't have the C preprocessor compare strings), be careful with __BASE_FILE__
because it may not correspond to your definition of "main" file. __BASE_FILE__
is the name of the file being compiled, so it's always equal to __FILE__
in source files, and only differs in headers and other included files.
In particular, __BASE_FILE__
is not the name of the file which contains the main()
function.
精彩评论