gcc проверяет, является ли файл основным (#if __BASE_FILE__ == __FILE__) - PullRequest
2 голосов
/ 02 января 2011

В ruby ​​есть очень распространенная идиома, чтобы проверить, является ли текущий файл «основным»:

  if __FILE__ == $0
    # do something here (usually run unit tests)
  end

Я хотел бы сделать что-то подобное в C после прочтения документации GCC Iя понял, что это должно работать так:

  #if __FILE__ == __BASE_FILE__
    // Do stuff
  #endif

единственная проблема - после того, как я попробую это:

$ 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

Я использую #if неправильно?

Как резюме для будущих гостей:

  • Вы не можете сравнивать строку, используя #, если
  • BASE_FILE - это имя файла, который компилируется (это на самом деле то, что ятребуемый).
  • Лучший способ сделать это - установить флаг во время компиляции с -D

Ответы [ 5 ]

6 голосов
/ 16 ноября 2012

в gcc вы можете использовать:

# if __INCLUDE_LEVEL__ == 0

или:

if (! __ INCLUDE_LEVEL __)

, чтобы проверить, если вашвнутри __BASE_FILE __

4 голосов
/ 02 января 2011

Да, вы неправильно используете #if.Это работает только для целочисленных константных выражений.Но даже если вы использовали if, сравнение указателей на равенство никогда не будет правильным способом сравнения строк в C.

2 голосов
/ 02 января 2011

Кажется, вы не можете.

В качестве альтернативы, он отлично работает при обычном условии if, и gcc может его оптимизировать.

if (!strcmp(__BASE_FILE__, __FILE__)) {
    // works.
}

, но вы не можете определить новые основные функции или использовать другие приемы препроцессора. но вы могли бы замкнуть главный с помощью статических методов, но это резко и грязно.

Но, возможно, тебе не следует этого делать. в Ruby / python это работает, потому что использование файлов выполняется во время выполнения. в C все файлы должны быть скомпилированы для использования.

Имейте в виду, что большинство систем сборки будет создавать по одному файлу за раз, создавая их как объектные файлы и восстанавливая их только при необходимости. Итак

 __BASE_FILE__ and __FILE__

будет равен большинству в исходных файлах, если не всегда. И я настоятельно рекомендую вам сделать это в заголовочных файлах.

Проще просто поместить свои тесты в отдельные файлы, связывая их только при необходимости.

1 голос
/ 02 января 2011

В дополнение к тому, что сказали другие (вы не можете иметь строки сравнения препроцессора C), будьте осторожны с __BASE_FILE__, поскольку оно может не соответствовать вашему определению «основного» файла.__BASE_FILE__ - это имя компилируемого файла, поэтому оно всегда равно __FILE__ в исходных файлах и отличается только заголовками и другими включенными файлами.

В частности, __BASE_FILE__ не является именемфайла, который содержит функцию main().

1 голос
/ 02 января 2011

Да, как говорят другие, вы злоупотребляете этим, поскольку вы не можете сравнивать строки таким образом в C, и особенно в препроцессоре.

Файл, который определяет int main(int argc, char* argv[]), является основным файлом. В исполняемом файле может быть только одна такая функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...