Ограничить область действия #define label

Какова правильная стратегия, чтобы ограничить сферу #define ярлыки и избежать необоснованного столкновения токенов?

В следующей конфигурации:

main.C

# include "Utility_1.h"# include "Utility_2.h"# include "Utility_3.h"VOID Main() { ... }

Utility_1.h

# define ZERO "Zero"# define ONE  "One"BOOL Utility_1(); // Uses- ZERO:"Zero" & ONE:"One"

Utility_2.h

# define ZERO '0'
# define ONE  '1'
BOOL Utility_2(); // Uses- ZERO:'0' & ONE:'1'

Utility_3.h

const UINT ZERO = 0;
const UINT ONE = 1;
BOOL Utility_3(); // Uses- ZERO:0 & ONE:1

Замечания: Utility _1, Utility_2 а также Utility_3 были написаны независимо


Ошибка: переопределение макроса и столкновение токена
Также, Больше всего беспокоит: Компилятор не указывает, что заменено, на что происходит замена токена

{Редактировать} Примечание. Это вопрос общего характера, поэтому, пожалуйста, не предлагайте enum или же const

что делать, когда: Я ДОЛЖЕН ИСПОЛЬЗОВАТЬ #define & _Пожалуйста, прокомментируйте мое предлагаемое решение ниже .. __

5

Решение

Правильная стратегия будет не использовать

#define ZERO '0'
#define ONE  '1'

совсем. Если вам нужны постоянные значения, используйте, в этом случае, const char вместо этого, завернутый в пространство имен.

12

Другие решения

Некоторые варианты:

  1. Используйте разные соглашения об использовании заглавных букв для макросов и обычных идентификаторов.

    const UINT Zero = 0;

  2. Подделайте пространство имен, добавив имя модуля к макросам:

    #define UTIL_ZERO '0'
    #define UTIL_ONE '1'

  3. Там, где это возможно (C ++), полностью отбрасывайте макросы и используйте реальное пространство имен:

    namespace util {
    const char ZERO = '0';
    const char ONE = '1';
    };

6

#defines не имеет области видимости, соответствующей коду C ++; Вы не можете ограничить это. Это наивные текстовые макросы замены. Представьте себе вопрос «как мне ограничить область, когда я заменяю текст на grep?»

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

правильный использование макросов почти самостоятельно решит эту проблему благодаря соглашению об именах. Если макрос назван как объект, он должен быть объект (а не макрос). Задача решена. Если макрос назван как функция (например, глагол), он должен быть функция.

Это относится к буквальным значениям, переменным, выражениям, операторам … все они не должны быть макросами. И это места, которые могут вас укусить.

В других случаях, когда вы используете как какой-то синтаксический помощник, имя вашего макроса почти наверняка не будет соответствовать соглашению об именах. Так что проблема почти ушла. Но самое главное, макросы, которые ДОЛЖНЫ быть макросами, будут вызывать ошибки компиляции при конфликте имен.

6

Какова правильная стратегия, чтобы ограничить область действия #define и избежать необоснованных коллизий токенов.

  1. Избегайте макросов, если они действительно не нужны. В C ++ константные переменные и встроенные функции обычно могут использоваться вместо этого. У них есть преимущество в том, что они типизированы и могут быть ограничены областью имен, классом или блоком кода. В Си макросы нужны чаще, но прежде чем вводить их, тщательно продумайте альтернативы.

  2. Используйте соглашение об именах, которое проясняет, какие символы являются макросами, а какие — идентификаторами уровня языка. Это обычно резервировать ALL_CAPITALS имена для исключительного использования макросов; если вы сделаете это, макросы могут столкнуться только с другими макросами. Это также привлекает внимание к частям кода, которые с большей вероятностью содержат ошибки.

  3. Включите префикс «псевдо-пространства имен» в каждое имя макроса, чтобы с меньшей вероятностью возникали конфликты макросов из разных библиотек / модулей / чего угодно и макросов с разными целями. Итак, если вы разрабатываете хитрую библиотеку, которая хочет определить символьную константу для цифры ноль, назовите ее примерно так DODGY_DIGIT_ZERO, Просто ZERO может означать много вещей, и вполне может конфликтовать с константой с нулевым значением, определенной другой хитрой библиотекой.

5

Есть два типа #define Макросы:

  1. Тот, который нужен только в не замужем файл. Давайте назовем их Private #defines
    например. PI 3.14 В этом случае:

    Согласно стандартной практике: правильная стратегия заключается в размещении #define метки — только в реализации, т.е. c, файлы а не заголовок h файл.

  2. Еще один, который нужен множественный файлы: давайте назовем эти Shared #defines
    например. EXIT_CODE 0x0BAD В этом случае:

    Размещайте только такие общие #define метки в заголовке h файл.

Дополнительно попробуйте назвать ярлыки однозначно с False NameSpaces или аналогичные соглашения, такие как префикс метки с MACRO_ например: #define MACRO_PI 3.14 так что вероятность столкновения уменьшает

4

Какова правильная стратегия, чтобы ограничить область действия #define и избежать необоснованных коллизий токенов.

Несколько простых правил:

  1. Сократите использование токенов препроцессора до минимума.
    Некоторые организации идут по этому пути и ограничивают символы препроцессора #include только охранники. Я не захожу так далеко, но хорошая идея сводить символы препроцессора к минимуму.

    • Используйте перечисления, а не именованные целочисленные константы.
    • использование const static переменные, а не именованные константы с плавающей точкой.
    • Используйте встроенные функции, а не макро-функции.
    • Используйте typedefs, а не #defined имена типов.
  2. Принять соглашение об именовании, которое исключает коллизии.
    Например,

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

const UINT ZERO = 0; // Programmer not aware of what's inside Utility.h

Прежде всего, если программист не знает, что находится внутри Utility.h, почему программист использовал это? #include заявление? Очевидно, что UINT пришел откуда-то …

Во-вторых, программист напрашивается на неприятности, называя переменную ZERO, Оставьте все эти заглавные буквы для символов препроцессора. Если вы следуете правилам, вам не нужно знать, что находится внутри Utility.h. Просто предположите, что Utility.h следует правилам. Сделать имя этой переменной zero,

1

Я думаю, что вы действительно должны знать, что вы в том числе. Это все равно что пытаться включить windows.h, а затем объявить переменную с именем WM_KEYDOWN. Если у вас есть коллизии, вы должны либо переименовать вашу переменную, либо (что-то вроде хака) #undef.

0

C — это язык структурированного программирования. Это имеет свои ограничения. Именно по этой причине объектно-ориентированные системы заняли 1-е место. В C, похоже, нет другого пути, чтобы понять, что переменные ваших заголовочных файлов начинаются с нотации _VARIABLE, чтобы было меньше шансов перезаписать их.

in header file
_ZERO 0

in regular file

ZERO 0
-2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector