Можно ли переопределить макрос без использования «undef»? - PullRequest
2 голосов
/ 11 июня 2019

Я пытаюсь разобраться в исходном коде libspatialindex . Будучи новичком в c ++, я с трудом нахожу голову над концепцией макросов. Оболочка API библиотеки для C, sidx_api.cc , прямо и косвенно включает в себя многочисленные заголовки, два из которых, по-видимому, определяют один и тот же макрос, связанный с взаимодействием с динамической библиотекой, без «undef»:

Tools.h

45 #if (defined _WIN32 || defined _WIN64 || defined WIN32 || defined WIN64) && !defined __GNUC__
46  #ifdef SIDX_DLL_EXPORT
47  #define SIDX_DLL __declspec(dllexport)
48  #else
49  #define SIDX_DLL __declspec(dllimport)
50  #endif
51 
52  // Nuke this annoying warning. See http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html
53 #pragma warning( disable: 4251 )
54 
55 #else
56  #define SIDX_DLL
57 #endif

sidx_export.h

29 #pragma once
30 
31 #ifndef SIDX_C_DLL  
32 #if defined(_MSC_VER)
33 # define SIDX_C_DLL __declspec(dllexport)
34 # define SIDX_DLL __declspec(dllexport)
35 #else
36 # if defined(USE_GCC_VISIBILITY_FLAG)
37 # define SIDX_C_DLL __attribute__ ((visibility("default")))
38 # define SIDX_DLL __attribute__ ((visibility("default")))
39 # else
40 # define SIDX_C_DLL
41 # define SIDX_DLL
42 # endif
43 #endif
44 #endif

Я считаю, что переопределение макроса без «undef» проблематично, например, как обсуждалось здесь и здесь . Я что-то здесь упускаю? Спасибо.

Ответы [ 2 ]

2 голосов
/ 11 июня 2019

Ни один макрос не был незаконно переопределен здесь.Некоторые могут быть определены более одного раза с одинаковыми определениями, что нормально.Это не идентичные определения, которые составляют проблему.

Сама DLL всегда создается с SIDX_DLL_EXPORT, определенным настройками проекта.Код, использующий DLL, создается без определения этого макроса.

Второй заголовок является частью DLL.Он всегда компилируется с определением SIDX_DLL_EXPORT.Таким образом, определенные им макросы, если они есть, всегда идентичны тем, которые определены в первом заголовке.Такое идентичное переопределение не представляет проблемы.

2 голосов
/ 11 июня 2019

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

С 6.10.3 Macroreplacement p2:

Идентификатор, определенный в настоящее время как объектоподобный макрос не должен переопределяться другой директивой предварительной обработки #define, если только второе определение не является объектно-подобным определением макроса и два списка замены не идентичны.

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

Так что в этих определениях используется shall.

Теперь, с 4.Conformance p2:

Если '' должен '' или 'не должен' 'требование, которое появляется вне ограничения, нарушено, поведение не определено.

Это официальное определение.Таким образом, не удаляя символ макроса из среды препроцессора (используя #undef) перед его переопределением, вы получите неопределенное поведение.

В случае, если вы обнаружите другую ситуацию в некоторых реализациях C, это не будет стандартизировано.

Правильно было бы вставить различные определения в функцию некоторого условия, которое вы задали снаружи:

#if COND
#define M M1
#else
#define M M2
#endif

Если вы используете какую-то библиотеку, которая переопределяет ее, наверняка есть некоторые макросы, которые устанавливают COND и делают вещи хорошо определенными.Вам нужно научиться пользоваться библиотекой.Переопределение его с другим списком токенов pp недопустимо.

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