Использование ранее определенного #define в новом #define в C

Существуют ли какие-либо потенциальные проблемы / опасности при выполнении таких действий, как

#define SAMPLERATE 32 // Sample rate in hertz #define ONE_MINUTE ( SAMPLERATE * 60 ) #define FIVE_MINUTES ( ONE_MINUTE * 5 ) 

Мой компилятор не выдает никаких ошибок или предупреждений. Это очень приятно, потому что я могу изменить одно значение #define (SAMPLERATE), а все остальные настроены на то, что им нужно, без каких-либо других изменений. Я просто не совсем уверен, что это лучшая практика или безопасна.

Обработчик #define обрабатывается препроцессором. Предпроцессор запускается до компиляции и может выполнять простые математические операции и копировать / вставлять код. Например, вы можете сделать следующее с вашим примером:

int myVar = SAMPLERATE;

SAMPLERATE просто вставляет 32 где SAMPLERATE перед компиляцией.

Этот механизм является мощным в том смысле, что теперь вы создали имя для целочисленного значения. Это добавляет смысл как для вас, так и для будущих разработчиков. Он также позволяет вам вносить изменения в одно место вместо многих.

Просто убедитесь, что #define SAMPLERATE 32 перед любыми другими операторами #define которые могут использовать SAMPLERATE .

Макросы НИКОГДА не расширяются в инструкции #define . Когда у вас есть #define :

 #define ONE_MINUTE ( SAMPLERATE * 60 ) 

Это определяет макрос ONE_MINUTE с расширением (телом) ( SAMPLERATE * 60 ) . Есть ли макрос, называемый SAMPLERATE определенный в другом месте вашей программы, или нет, совершенно не имеет значения. Экзистенция (или небытие) такого макроса не имеет никакого эффекта.

Вместо этого, когда используется макрос (и макрос расширяется), результат этого расширения повторно сканируется для расширения других макросов. Таким образом, все, что имеет значение, определяется, определяется ли SAMPLERATE в точке, в которой используется ONE_MINUTE .

Константы #define (объектно-ориентированные macros) используются препроцессором для подстановки идентификатора с указанным списком маркеров. #defines также может принимать параметры. Они называются функциональными макросами. Преимущество таких макросов заключается в том, что они заменяются в строке, что вы не всегда можете гарантировать с помощью обычных функций. Объектно-ориентированные macros часто используются в условной компиляции. Недостаток макросов, на мой взгляд, заключается в том, что они не безопасны для типа. При использовании тщательно, однако, они могут быть большой помощью.

Вот пример макросов, облегчающих вашу жизнь.

 #include  #include  static const unsigned char BYTES[256] = { #define A(n) n, n+1, n+1, n+2 #define B(n) A(n), A(n+1), A(n+1), A(n+2) #define C(n) B(n), B(n+1), B(n+1), B(n+2) C(0), C(1), C(1), C(2) }; int main() { unsigned char BYTE = 0b01011101; printf("The byte 01011101 has %d set bits.\n",BYTES[BYTE]); }