Почему для #define не требуется точка с запятой?

Я написал тестовый код в 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 не константами?

Ответы

Ответ 1

#define является директивой препроцессора, а не выражением или декларацией, как определено в грамматике C (оба из них необходимо положить точку с запятой). Правила для синтаксиса каждого из них различны.

Ответ 2

#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.

Ответ 3

define является препроцессорной директивой и является простой заменой, это не декларация.

BTW, в качестве замены он может содержать в себе часть ;:

// Ugly as hell, but valid 
#define END_STATEMENT ;

int a = 1 END_STATEMENT // preprocessed to -> int a = 1;

Ответ 4

Обе константы? Нет.

Первый метод не создает константу на языке C. Константные переменные не квалифицируются как константы в C. Ваш первый метод работает только потому, что компиляторы last-C99 C поддерживают массивы переменной длины (VLA). Ваш buffer является VLA в первом случае специально, потому что MAX_STRING не является константой. Попробуйте объявить тот же массив в области файлов, и вы получите сообщение об ошибке, поскольку VLA не разрешены в области файлов.

Второй метод может использоваться для назначения имен постоянным значениям на C, но вы должны сделать это правильно. ; в определении макроса не должно быть. Макросы работают с помощью текстовой подстановки, и вы не хотите подставлять этот дополнительный ; в объявление массива. Правильный способ определения этого макроса будет

#define MAX_STRING 256

В языке C, когда дело доходит до определения правильных именованных констант, вы в основном ограничены макросами и перечислениями. Не пытайтесь использовать константы const ", если вы действительно не знаете, что он будет работать для ваших целей.

Ответ 5

Вторая версия не определяет константу в отношении языка, а просто правило подстановки для блока текста. Когда препроцессор выполнил эту работу, компилятор видит

char buffer [256;];

который не является синтаксически действительным.

Мораль истории: предпочитайте const int MAX_STRING = 256; способ, который помогает вам, компилятору и отладчику.

Ответ 6

Так как синтаксис был решен для директив прекомпилятора.

Операции завершаются с ; в c/С++, #define - это предпроцессорная директива, а не оператор.

Ответ 7

Эта директива препроцессора:

#define MAX_STRING 256;

указывает препроцессору заменить все MAX_STRING на 256; - и точкой с запятой. Операторам препроцессора не требуется точка с запятой в конце. Если вы положите один, препроцессор на самом деле думает, что вы имеете в виду его с точкой с запятой.

Если вы запутались с #define для констант, const int, вероятно, будет легче понять.

Если вы хотите узнать больше о том, как правильно использовать эти препроцессорные директивы, попробуйте посмотреть этот сайт.