Какой смысл определять аргументы в другом файле заголовка?

#c #coding-style

#c #стиль кодирования

Вопрос:

Итак, я просматривал некоторый код, и есть некоторые вещи, которые я не могу понять. У меня есть два файла заголовка. Один из них называется ‘args.h’ и в этом есть эти утверждения, среди прочих:

 #if (defined(__cplusplus) || defined(__STDC__) || defined(c_plusplus))
#define NEW_STYLE 1
#define VOID    void
#define ARGS(parenthesized_list) parenthesized_list
#else
#define NEW_STYLE 0
#define VOID
#define ARGS(parenthesized_list) ()
#define const
#endif

#if !defined(EXIT_SUCCESS)
#define EXIT_SUCCESS    0
#define EXIT_FAILURE    1
#endif
  

В другом заголовочном файле прототипы функций объявляются следующим образом:

 #if defined(__cplusplus)
extern "C" {
#endif

extern void     yyerror ARGS((const char *s_));
extern int      yylex ARGS((void));
extern int      yyparse ARGS((void));
extern int      yywrap ARGS((void));

#if defined(__cplusplus)
}
#endif
  

и куча других вещей.

Итак, мои вопросы:

1> Что именно делает #define const?

2> Почему arg объявлен в другом заголовочном файле? Не могли бы мы просто объявить функции как обычный extern void a(const char *s__)? Или это просто предпочтение стиля?

Спасибо.

Комментарии:

1. ой, я надеюсь, что после этого это const исправится #undef .

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

3. Да, это не определено позже. Конкретный случай, на который я ссылаюсь, относится к файлу lex, где эти два файла использовались в качестве заголовков к файлу lex.

Ответ №1:

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

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

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

Комментарии:

1. «подобный код был распространен» был ли он настолько распространенным, что даже не стоил комментария, или по крайней мере #ifndef __STDC_VERSION__ ? Или мы можем с уверенностью сказать, что автор — хулиган? 😉

2. @Steve Jessop: Это было достаточно распространено, и я ожидал, что почти любой, кто писал на C в то время, довольно легко его распознает. Скорее всего, этот «хулиган» был довольно прогрессивным, добавляя const прототипы и в код, в котором раньше их полностью не было. __STDC_VERSION__ в то время это было ненадежно.

3. Я бы определенно хотел, чтобы аргументы были где-то определены «правильно», чтобы у меня могли быть прототипы в компиляторах, которые их поддерживают, а затем выбрать, какую версию #define во время конфигурации. Итак, я немного удивлен, что в файле нет ничего, объясняющего, как на самом деле должны работать АРГУМЕНТЫ — если он расширяется до () во всех сборках и компиляторах, тогда вы можете вообще не утруждать себя указанием списка параметров.

4. @Steve Jessop: по крайней мере, в большинстве случаев это было определено «правильно» где-то или иным образом, но это определение зависело от (часто непонятного, неразборчивого) определения используемого компилятора / версии. Поскольку код компилируется таким образом, люди, наивно переносящие код на новый компилятор, могут легко исключить обнаружение компилятора и просто оставить это.

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

Ответ №2:

Это настройки, позволяющие сделать код переносимым среди компиляторов, лишенных той или иной функции

  1. удаляет ли const везде (наверняка не очень хорошая идея, если у вас современный компилятор)
  2. это связано с синтаксисом ANSI C