Препроцессор C может использоваться, чтобы сказать, существует ли файл?

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

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

63
задан Brian Tompsett - 汤莱恩 1 February 2016 в 19:22
поделиться

7 ответов

Обычно это сделано при помощи сценария, который пытается выполнить препроцессор на попытке включения файла. В зависимости от того, если препроцессор возвращает ошибку, сценарий обновляет сгенерированный.h файл с соответствующим #define (или #undef). В ударе сценарий мог бы неопределенно походить на это:

cat > .test.h <<'EOM'
#include <asdf.h>
EOM
if gcc -E .test.h
 then
  echo '#define HAVE_ASDF_H 1' >> config.h
 else 
  echo '#ifdef HAVE_ASDF_H' >> config.h
  echo '# undef HAVE_ASDF_H' >> config.h
  echo '#endif' >> config.h
 fi

А довольно полная платформа для того, чтобы портативно работать с проверками мобильности как это (а также тысячи других) autoconf.

30
ответ дан s4y 24 November 2019 в 16:11
поделиться

Создайте специальную папку для недостающих заголовков и сделайте ту папку, которая будет искаться в последний раз
(который является compliler конкретный - последний объект во "ВКЛЮЧАЕТ" переменную среды, что-то как этот)

Тогда, если некоторый header1.h может отсутствовать, создайте в той папке тупик

header1.h:

#define header1_is_missing

Теперь можно всегда писать

#include <header1.h>
#ifdef header1_is_missing

   // there is no header1.h 

#endif
47
ответ дан eugensk 24 November 2019 в 16:11
поделиться

Сам препроцессор не может определить существование файлов, но, конечно, можно использовать среду сборки, чтобы сделать так. Я главным образом знаком с, делают, который позволил бы Вам делать что-то вроде этого в своем make-файле:

ifdef $(test -f filename && echo "present")
  DEFINE=-DFILENAME_PRESENT
endif

, Конечно, необходимо было бы найти аналог к этому в других средах сборки как VisualStudio, но я уверен, что они существуют.

8
ответ дан bmdhacks 24 November 2019 в 16:11
поделиться

У Вас мог быть шаг перед сборкой, выполненный, который генерирует включать файл, который содержит список #defines, которые представляют названия файлов, существующих в текущем каталоге:

#define EXISTS_FILE1_C
#define EXISTS_FILE1_H
#define EXISTS_FILE2_C

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

4
ответ дан Greg Hewgill 24 November 2019 в 16:11
поделиться

Насколько я знаю, что cpp не имеет директивы относительно существования файла.

Вы могли бы быть в состоянии выполнить это с небольшим количеством справки от Make-файла при использовании того же, делают через платформы. Можно обнаружить присутствие файла в Make-файле:

foo.o: foo.c
    if [ -f header1.h ]; then CFLAGS+=-DHEADER1_INC

Как @Greg упоминания Hewgill, можно тогда заставить #includes быть условным выражением:

#ifdef HEADER1_INC
#include <header1.h>
#endif
4
ответ дан DGentry 24 November 2019 в 16:11
поделиться

Другая возможность: заполните каталог где-нибудь с версиями нулевой длины всех заголовков, которые Вы хотите дополнительно включать. Передайте-I аргумент этому каталогу как последний такая опция.

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

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

4
ответ дан DGentry 24 November 2019 в 16:11
поделиться

Мне пришлось сделайте нечто подобное для ОС Symbian. Вот как я это сделал: допустим, вы хотите проверить, существует ли файл "file_strange.h", и вы хотите включить некоторые заголовки или ссылку на некоторые библиотеки в зависимости от наличия этого файла.

сначала создайте небольшой пакетный файл для проверки его существования. файл.

autoconf - это хорошо, но для многих небольших проектов он не подходит.

---------- check.bat

@echo off

IF EXIST [\epoc32\include\domain\middleware\file_strange] GOTO NEW_API
GOTO OLD_API
GOTO :EOF

:NEW_API
echo.#define NEW_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

:OLD_API
echo.#define OLD_API_SUPPORTED>../inc/file_strange_supported.h
GOTO :EOF

---------- check.bat заканчивается

затем я создал файл gnumake

---------- checkmedialist.mk

do_nothing :
    @rem do_nothing

MAKMAKE : 
        check.bat

BLD : do_nothing

CLEAN : do_nothing

LIB : do_nothing

CLEANLIB : do_nothing

RESOURCE : do_nothing

FREEZE : do_nothing

SAVESPACE : do_nothing

RELEASABLES : do_nothing

FINAL : do_nothing

---------- check.mk заканчивается

включает check.mk файл в вашем файле bld.inf, он ДОЛЖЕН быть перед вашими файлами MMP

PRJ_MMPFILES
gnumakefile checkmedialist.mk

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

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
LIBRARY newapi.lib
#else
LIBRARY oldapi.lib
#endif

и в .cpp

#include "../inc/file_strange_supported.h"
#ifdef NEW_API_SUPPORTED
CStrangeApi* api = Api::NewLC();
#else
// ..
#endif
2
ответ дан 24 November 2019 в 16:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: