#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:
Это настройки, позволяющие сделать код переносимым среди компиляторов, лишенных той или иной функции
- удаляет ли const везде (наверняка не очень хорошая идея, если у вас современный компилятор)
- это связано с синтаксисом ANSI C