2014-01-09 4 views
5

Существуют ли какие-либо потенциальные проблемы/опасности в делать что-то такое, какИспользование предварительно определенного #define в новом #define в C

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

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

+7

Нет проблем вообще –

+0

Вы можете проверить его самостоятельно - посмотрите на сборку. – wondra

+0

Это именно то, что вы должны делать, не о чем беспокоиться –

ответ

6

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

int myVar = SAMPLERATE;

Предварительно процессор будет просто вставить 32 где SAMPLERATE находится перед компилируется.

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

Только обязательно #define SAMPLERATE 32 до любых других #define утверждений, которые могут использовать SAMPLERATE.

+0

Так что, если бы я сделал 'int myVar = FIVE_MINUTES;' заменил бы 'FIVE_MINUTES' на 32 * 60 * 5 или только на значение 9600? – Oilyraincloud

+0

Вы отвечаете правильно, но, возможно, немного глубоко для вопроса, который был задан. –

+2

@bblincoe: no - это неверно - препроцессор просто выполняет замену текста. Однако компилятор обычно сокращает любое выражение постоянной времени компиляции до одного значения. –

0

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

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

#include <stdio.h> 
#include <stdlib.h> 

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]); 
} 
+1

Вид ответа не по теме, нет? –

+0

Возможно, у меня вопрос неправильный. Я просто заявляю, что определения полезны и используются много, и код был просто примером, который я готов. Ну, пример использует макросы вместо простых констант, так что, возможно, вы имеете в виду это? – Veritas

+0

OP не спрашивал о макросах. – bblincoe

5

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

#define ONE_MINUTE (SAMPLERATE * 60) 

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

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

Смежные вопросы