Зачем использовать #define вместо переменной - PullRequest
51 голосов
/ 15 мая 2011

Какой смысл #define в C ++?Я видел только примеры, в которых он используется вместо «магического числа», но я не вижу смысла просто вместо этого присваивать это значение переменной.

Ответы [ 8 ]

112 голосов
/ 15 мая 2011

#define является частью языка препроцессора для C и C ++.Когда они используются в коде, компилятор просто заменяет оператор #define на то, что вам нужно.Например, если вам надоело писать for (int i=0; i<=10; i++) все время, вы можете сделать следующее:

#define fori10 for (int i=0; i<=10; i++)

// some code...

fori10 {
    // do stuff to i
}

Если вы хотите что-то более общее, вы можете создать макросы препроцессора:

#define fori(x) for (int i=0; i<=x; i++)
// the x will be replaced by what ever is put into the parenthesis, such as
// 20 here
fori(20) {
    // do more stuff to i
}

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

// compile the following if debugging is turned on and defined
#ifdef DEBUG
// some code
#endif

Большинство компиляторов позволяют вам определятьмакрос из командной строки (например, g++ -DDEBUG something.cpp), но вы также можете просто вставить определение в ваш код следующим образом:

#define DEBUG

Некоторые ресурсы:

  1. Статья в Википедии
  2. Сайт на C ++
  3. Документация по препроцессору GCC
  4. Справочник Microsoft
  5. специфичный для C сайт (хотя я не думаю, что он отличается от версии C ++)
41 голосов
/ 15 мая 2011

В основном стилистический в наши дни.Когда C был молодым, не было такого понятия, как переменная const.Поэтому, если вы используете переменную вместо #define, у вас нет гарантии, что кто-то где-то не изменит ее значение, что приведет к хаосу во всей вашей программе.

В старые времена FORTRAN передавал даже константык подпрограммам по ссылке, и было возможно (и вызывает головную боль) изменить значение константы, такой как '2', на нечто иное.Однажды это произошло в программе, над которой я работал, и единственный намек на то, что что-то не так, был в том, что мы получили ABEND (ненормальный конец), когда программа достигла значения STOP 999, которое должно было нормально завершиться.

23 голосов
/ 25 мая 2013

Однажды у меня были проблемы на работе. Меня обвинили в использовании "магических чисел" в объявлениях массива.

Как это:

int Marylyn[256], Ann[1024];

Политика компании состояла в том, чтобы избегать этих магических чисел, потому что, как мне объяснили, эти числа не были переносимы; что они мешали легкому обслуживанию. Я утверждал, что когда я читаю код, я хочу точно знать, насколько велик массив. Я проиграл спор и поэтому в пятницу днем ​​я заменил оскорбительные «магические числа» на #defines, например:

 #define TWO_FIFTY_SIX 256
 #define TEN_TWENTY_FOUR 1024

 int Marylyn[TWO_FIFTY_SIX], Ann[TEN_TWENTY_FOUR];

В следующий понедельник днем ​​меня вызвали и обвинили в пассивных вызывающих тенденциях.

7 голосов
/ 15 мая 2011

C раньше не использовал констант, поэтому #defines были единственным способом предоставления постоянных значений.Они есть и в C, и в C ++, поэтому нет смысла их использовать, кроме случаев, когда они будут тестироваться с помощью # ifdef / ifndef.

7 голосов
/ 15 мая 2011

#define может выполнять некоторые задачи, которые не могут выполнять обычные C ++, такие как защита заголовков и другие задачи. Однако его определенно не следует использовать в качестве магического числа - вместо него следует использовать статический констант.

4 голосов
/ 15 мая 2011

Чаще всего (кроме объявления констант) используется include guard .

1 голос
/ 15 мая 2011

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

Вот пара примеров, которые используют определение, которое не может быть заменено переменной:

  1. #определить min (i, j) (((i) <(j))? (i): (j)) <br>обратите внимание, что это оценивается препроцессором, а не во время выполнения

  2. http://msdn.microsoft.com/en-us/library/8fskxacy.aspx

0 голосов
/ 15 мая 2011

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

// File:  MyFile.h

// This header will compile to size-zero.
#define TAX_RATE 0.625

// NO:  static const double TAX_RATE = 0.625;
// NO:  extern const double TAX_RATE;  // WHAT IS THE VALUE?

РЕДАКТИРОВАТЬ: Как Нил указывает в комментарии к этому посту, явное определение со значением в заголовке будет работать для C ++, но не C.

...