Если у меня есть:
#define MAXLINE 5000
Какой тип MAXLINE понимается? Должен ли я предположить, что это int
? Могу ли я проверить его каким-то образом?
В общем, как определить тип переменной #define
ed?
Если у меня есть:
#define MAXLINE 5000
Какой тип MAXLINE понимается? Должен ли я предположить, что это int
? Могу ли я проверить его каким-то образом?
В общем, как определить тип переменной #define
ed?
У него нет типа. Это простая замена текста. Текст 5000 будет опущен на место, где MAXLINE будет отображаться как токен.
Например:
int a = MAXLINE;
поместит значение 5000 в a
.
В то время как
char *MAXLINE2 = "MAXLINE";
не приведет к
char *50002 = "5000";
Итак, если вам нужна проверка типов, макрос не подходит. Вместо этого вам захочется объявить статические константы, таким образом, проверка типов выполняется компилятором.
Для информации о различиях между static
, const
и #define
существует много источников, включая этот вопрос: Static, define и const в C
компилятор никогда не видит эту строку кода, препроцессор работает до фактической компиляции и заменяет эти макросы своими литеральными значениями, см. ссылку ниже для получения дополнительной информации
(Очень!) В целом, ваш компилятор C будет выполнять три задачи при выполнении:
Запустите предварительный проход через исходные файлы,
Запустите компилятор над предварительно обработанными исходными файлами
Запустите компоновщик по результирующим объектным файлам.
Строки, начинающиеся с символа #
, как линия
#define MAXLINE 5000
обрабатывается фазой препроцессора. (упрощенно) Препроцессор будет анализировать файл и выполнять замену текста для любых макросов, которые он обнаруживает. В препроцессоре нет понятия типов.
Предположим, что у вас есть следующие строки в исходном файле:
#define MAXLINE 5000
int someVariable = MAXLINE; // line 2
char someString[] = "MAXLINE"; // line 3
Препроцессор будет обнаруживать макрос MAXLINE
в строке 2 и будет выполнять замену текста. Обратите внимание, что в строке 3 "MAXLINE"
не рассматривается как макрос, поскольку это строковый литерал.
После завершения фазы препроцессора на этапе компиляции будет отображаться только следующее:
int someVariable = 5000; // line 2
char someString[] = "MAXLINE"; // line 3
(комментарии были оставлены для ясности, но обычно удаляются препроцессором)
Вероятно, вы можете использовать опцию в компиляторе для проверки вывода препроцессора. В gcc опция -E
сделает это.
Обратите внимание, что хотя препроцессор не имеет понятия типа, нет причин, по которым вы не можете включать тип макроса для полноты. например.
#define MAXLINE ((int)5000)
У него нет типа. Это просто токен, который препроцессор будет помещать в исходный код перед передачей кода компилятору. Вы можете сделать это (смешное), чтобы объявить переменную с именем x5000
:
#define APPEND(x,y) x ## y
int main() {
int APPEND(x,5000);
x5000 = 3;
}
Препроцессор превращает это в это, прежде чем передать ему собственно компилятор:
int main() {
int x5000;
x5000 = 3;
}
Итак, только потому, что вы видите 5000
в макросе, это не значит, что оно должно быть числовым.
MAXLINE
не является переменной вообще. На самом деле это не синтаксис C. Часть процесса компиляции запускает препроцессор перед компилятором, и одно из действий, которое выполняет препроцессор, заключается в замене экземпляров тегов MAXLINE
в исходном файле тем, что приходит после #define MAXLINE
(5000 в вопросительном коде).
Кроме того, еще один общий способ использования препроцессора в вашем коде - это директива #include
, которую препроцессор просто заменяет предварительно обработанным содержимым включенного файла.
Посмотрите пример процесса компиляции в действии. Здесь файл foo.c
, который будет использоваться в примерах:
#define VALUE 4
int main()
{
const int x = VALUE;
return 0;
}
Я использую gcc
и cpp
(препроцессор C) для примеров, но вы, вероятно, можете сделать это с помощью любого компилятора у вас есть, с разными флагами, конечно.
Сначала скомпилируйте foo.c
с помощью gcc -o foo.c
. Что случилось? Это сработало; теперь вы должны иметь исполняемый файл foo
.
Вы можете сказать gcc
только для предварительной обработки и не компиляции. Если вы выполните gcc -E foo.c
, вы получите предварительно обработанный файл на стандартном. Вот что он производит:
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "foo.c"
int main()
{
const int x = 4;
return 0;
}
Обратите внимание, что первая строка main
заменила VALUE
на 4
.
Вам может быть интересно, что такое первые четыре строки. Они называются linemarkers, и вы можете прочитать о них больше в Выход препроцессора.
Насколько я знаю, вы не можете прямо пропустить предварительную обработку в gcc
, но существует пара подходов, чтобы сказать, что файл уже был предварительно обработан. Однако, даже если вы это сделаете, оно удалит макросы, присутствующие в файле, потому что они не предназначены для потребления компилятора. Вы можете видеть, с чем работает компилятор в этой ситуации с помощью gcc -E -fpreprocessed foo.c
:
.
.
.
.
int main()
{
const int x = VALUE;
return 0;
}
Примечание. Я помещаю точки вверху; притворяйтесь, что это пустые строки (мне пришлось поместить их туда, чтобы эти строки отображались SO).
Этот файл явно не будет компилироваться (попробуйте gcc -fpreprocessed foo.c
, чтобы узнать), потому что VALUE
присутствует в источнике, но не определен нигде.
Мы называем этот макрос или препроцессор, который используется для строкового замещения содержимого исходного файла. Прочитайте это: https://en.wikipedia.org/wiki/C_macro
Да, вы можете считать это int
.
Ну, на самом деле все остальные ответы верны. Это не C, это просто
директива, которая сообщает препроцессору сделать некоторые текстовые
подстановок, и поэтому он не имеет типа. Однако, если вы не сделаете
фанки с ним (как трюк ## препроцессора), вы будете
обычно используют MAXLINE
как некоторая константа, а препроцессор
заменит его на 5000
, который действительно является явной константой. А также
константы имеют тип: 5000
- int
. Константа, написанная как
десятичное целое, без суффикса (например, U или L), будет интерпретироваться
компилятор как int
, long int
или unsigned long int
: первый
этих типов, которые подходят.
Но это, конечно же, не имеет ничего общего с предварительным процессором. Ты мог
перепишите свой вопрос как "какой тип 5000
?", без
#define
.