Тип #define переменных - PullRequest
       1

Тип #define переменных

41 голосов
/ 21 декабря 2011

Если у меня есть:

#define MAXLINE    5000

Какой тип понимается под MAXLINE?Должен ли я считать, что это int?Можно ли как-нибудь проверить это?

В общем, как определить тип #define ed переменной?

Ответы [ 7 ]

45 голосов
/ 21 декабря 2011

У него нет типа.Это простая текстовая замена.Текст 5000 будет сброшен на место везде, где MAXLINE появляется в качестве токена.

Например:

int a = MAXLINE;

поместит значение 5000 в a.

, а

char *MAXLINE2 = "MAXLINE";

не приведет к

char *50002 = "5000";

Так что, если вы хотите проверять тип, макросы не подходят.Вместо этого вы захотите объявить статические константы, таким образом, проверка типов выполняется компилятором.

Для получения информации о различиях между static, const и #define существует множество источников, включая этот вопрос: Static, define и const в C

9 голосов
/ 21 декабря 2011

(Очень!) В общем, ваш компилятор C при выполнении будет выполнять 3 задачи:

  1. Выполнить проход предварительной обработки ваших исходных файлов,

  2. Запуск компилятора над предварительно обработанными исходными файлами

  3. Запуск компоновщика над результирующими объектными файлами.

Строки, начинающиеся с #, как и строка


#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)
5 голосов
/ 21 декабря 2011

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

http://www.cplusplus.com/doc/tutorial/preprocessor/

3 голосов
/ 21 декабря 2011

У него нет типа. Это просто токен, который препроцессор вставит в исходный код перед передачей кода компилятору. Вы можете сделать эту (нелепую) вещь, чтобы объявить переменную с именем x5000:

#define APPEND(x,y) x ## y

int main() {
        int APPEND(x,5000);
        x5000 = 3;
}

Препроцессор превращает это в это перед тем, как передать его самому компилятору:

int main() {
        int x5000;
        x5000 = 3;
}

То есть, если вы видите 5000 в макросе, это не значит, что он должен быть числовым.

2 голосов
/ 21 декабря 2011

MAXLINE вообще не является переменной. На самом деле это не синтаксис Си. Часть процесса компиляции запускает препроцессор перед компилятором, и одно из действий, которые предпринимает препроцессор, заключается в замене экземпляров 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.

Возможно, вам интересно, какие первые четыре строки. Они называются линейными маркерами, и вы можете прочитать о них больше в Выход препроцессора .

Компиляция без предварительной обработки

Насколько я знаю, вы не можете сразу пропустить предварительную обработку в gcc, но существует пара подходов, чтобы сказать, что файл уже был предварительно обработан. Однако даже если вы сделаете это, он удалит макросы, присутствующие в файле, поскольку они не предназначены для использования компилятором. Вы можете увидеть, с чем работает компилятор в этой ситуации с gcc -E -fpreprocessed foo.c:

.
.
.
.
int main()
{
  const int x = VALUE;
  return 0;
}

Примечание: я положил точки сверху; притвориться, что это пустые строки (мне пришлось поместить их туда, чтобы эти строки отображались SO).

Этот файл явно не скомпилируется (попробуйте gcc -fpreprocessed foo.c, чтобы выяснить это), потому что VALUE присутствует в источнике, но нигде не определен.

1 голос
/ 21 декабря 2011

Да, вы можете предположить, что это int.

Ну, на самом деле все остальные ответы верны. Это не С, это просто директива, которая говорит препроцессору делать некоторые текстовые замены, и как таковой он не имеет типа. Однако, если вы не делаете никаких прикольные вещи с ним (как трюк ## препроцессора), вы будете обычно используют MAXLINE как некоторую константу, и препроцессор заменит его на 5000, который действительно является явной константой. А также константы имеют тип: 5000 - это int. Константа, написанная как десятичное целое число без суффикса (например, U или L) будет интерпретироваться как компилятор как int, long int или unsigned long int: первый из этих типов, который подходит.

Но это, конечно, не имеет ничего общего с препроцессором. Вы могли бы перепишите ваш вопрос как «какой тип 5000?», без #define.

1 голос
/ 21 декабря 2011

Мы называем этот макрос или препроцессор, который используется для строковой замены содержимого исходного файла.Читать это: https://en.wikipedia.org/wiki/C_macro

...