Ответ 1
#define
является директивой препроцессора, а не выражением или декларацией, как определено в грамматике C (оба из них необходимо положить точку с запятой). Правила для синтаксиса каждого из них различны.
Я написал тестовый код в C. По ошибке я вставил a ;
после #define
, что дало мне ошибки. Почему точка с запятой не требуется для #define
s?
Более конкретно:
Метод 1: работает
const int MAX_STRING = 256;
int main(void) {
char buffer[MAX_STRING];
}
Метод 2: не работает - ошибка компиляции.
#define MAX_STRING 256;
int main(void) {
char buffer[MAX_STRING];
}
В чем причина различного поведения этих кодов? Являются ли эти MAX_STRING не константами?
#define
является директивой препроцессора, а не выражением или декларацией, как определено в грамматике C (оба из них необходимо положить точку с запятой). Правила для синтаксиса каждого из них различны.
#define MAX_STRING 256;
означает:
всякий раз, когда вы находите MAX_STRING при предварительной обработке, замените его на 256;
. В вашем случае это сделает метод 2:
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING 256;
int main(void) {
char buffer [256;];
}
который является недопустимым синтаксисом. Заменить
#define MAX_STRING 256;
с
#define MAX_STRING 256
Разница между двумя вашими кодами заключается в том, что в первом методе вы объявляете константу равной 256
, но во втором коде вы определяете MAX_STRING
для обозначения 256;
в исходном файле.
Директива #define используется для определения значений или макросов, которые используются препроцессором для управления исходным кодом программы до его компиляции. Поскольку определения препроцессора заменяются до того, как компилятор воздействует на исходный код, любые ошибки, которые вводятся с помощью #define, трудно отследить.
Синтаксис:
#define CONST_NAME VALUE
если в конце есть ;
, он считается частью VALUE
.
чтобы понять, как работает #define
, попробуйте определить:
#define FOREVER for(;;)
...
FOREVER {
/perform something forever.
}
Интересное замечание John Hascall:
Большинство компиляторов предоставят вам возможность увидеть результат после фазы препроцессора, это может помочь в таких проблемах отладки.
В gcc
это можно сделать с флагом -E
.
define
является препроцессорной директивой и является простой заменой, это не декларация.
BTW, в качестве замены он может содержать в себе часть ;
:
// Ugly as hell, but valid
#define END_STATEMENT ;
int a = 1 END_STATEMENT // preprocessed to -> int a = 1;
Обе константы? Нет.
Первый метод не создает константу на языке C. Константные переменные не квалифицируются как константы в C. Ваш первый метод работает только потому, что компиляторы last-C99 C поддерживают массивы переменной длины (VLA). Ваш buffer
является VLA в первом случае специально, потому что MAX_STRING
не является константой. Попробуйте объявить тот же массив в области файлов, и вы получите сообщение об ошибке, поскольку VLA не разрешены в области файлов.
Второй метод может использоваться для назначения имен постоянным значениям на C, но вы должны сделать это правильно. ;
в определении макроса не должно быть. Макросы работают с помощью текстовой подстановки, и вы не хотите подставлять этот дополнительный ;
в объявление массива. Правильный способ определения этого макроса будет
#define MAX_STRING 256
В языке C, когда дело доходит до определения правильных именованных констант, вы в основном ограничены макросами и перечислениями. Не пытайтесь использовать константы const
", если вы действительно не знаете, что он будет работать для ваших целей.
Вторая версия не определяет константу в отношении языка, а просто правило подстановки для блока текста. Когда препроцессор выполнил эту работу, компилятор видит
char buffer [256;];
который не является синтаксически действительным.
Мораль истории: предпочитайте const int MAX_STRING = 256;
способ, который помогает вам, компилятору и отладчику.
Так как синтаксис был решен для директив прекомпилятора.
Операции завершаются с ;
в c/С++, #define
- это предпроцессорная директива, а не оператор.
Эта директива препроцессора:
#define MAX_STRING 256;
указывает препроцессору заменить все MAX_STRING
на 256;
- и точкой с запятой. Операторам препроцессора не требуется точка с запятой в конце. Если вы положите один, препроцессор на самом деле думает, что вы имеете в виду его с точкой с запятой.
Если вы запутались с #define
для констант, const int
, вероятно, будет легче понять.
Если вы хотите узнать больше о том, как правильно использовать эти препроцессорные директивы, попробуйте посмотреть этот сайт.