Почему Макросы использования в C? [дубликат]

Вы можете, существует несколько способов сделать это по сети, или прямой. Вот объяснение: http://linuxibos.blogspot.com/2012/05/seprinters-linux.html На низе той страницы можно загрузить сервер печати Linux, который является, я думаю лучшее решение для проблемы.

48
задан Community 23 May 2017 в 02:17
поделиться

11 ответов

Одна из причин заключалась в том, что до C99 ключевое слово inline не было стандартом для языка C. Таким образом, макросы позволили вам встраивать небольшие функции. Они также в некотором роде работают как шаблоны, т.е. вам не нужно указывать типы в определении макроса, например:

#define MAX(x,y) ((x) > (y) ? (x) : (y))

Этот макрос совместим с целыми числами, числами типа double, float и т. д.

45
ответ дан 7 November 2019 в 12:06
поделиться

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

16
ответ дан 7 November 2019 в 12:06
поделиться

Sometimes you want to do logging, but only in debug mode. So you write something like:

#ifdef DEBUG
#define LOG_MSG(x) printf(x);
#else
#define LOG_MSG(X)
#endif

Sometimes you just want to turn something off or on based on a compile-time switch. E.g., my company does some co-branding of our product and partners ask to turn things off. So we'll do something like:

#ifndef SPECIAL_PARTNER_BUILD
    DoSomethingReallyAwesome();
#endif

Then build with -DSPECIAL_PARTNER_BUILD when giving the partner drops.

Among many other possible reasons.

Sometimes you just want to save typing for things you do over and over again. Some people take this to far (cough MFC cough) and write what amounts to their own language in Macros to abstract away a difficult API. This makes debugging a frikkin' nightmare.

12
ответ дан 7 November 2019 в 12:06
поделиться

Мы использовали этот тип макроса в нашем коде:

// convenience macros for implementing field setter/getter functions
#ifndef CREATE_GET_SET
#define CREATE_GET_SET(PREFIX, FIELD_NAME,FIELD_DATATYPE) \
  protected:\
    FIELD_DATATYPE PREFIX ## FIELD_NAME;\
  public:\
  inline FIELD_DATATYPE get ## _ ## FIELD_NAME(void) const\
  { \
    return(PREFIX ## FIELD_NAME); \
  } \
  inline void set ## _ ## FIELD_NAME(FIELD_DATATYPE p) \
  { \
    PREFIX ## FIELD_NAME = p; \
  }
#endif

внутри класса / структуры вы должны определить переменную :

CREATE_GET_SET(_, id, unsigned int);

Это определит вашу переменную и создаст общий метод получения / установки для кода. Это просто обеспечивает более чистую и последовательную генерацию кода для get / set. Конечно, вы можете все это написать, но это очень много шаблонного кода. ПРИМЕЧАНИЕ: это всего лишь один из пары макросов. Я их все не публиковал. Вы бы не стали так обращаться со словом «char *» (где вы хотите установить strncpy или strcpy для данных). Это была простая демонстрация того, что вы можете делать с макросом и некоторыми простыми типами.

2
ответ дан 7 November 2019 в 12:06
поделиться

Макросы C могут генерировать код во время компиляции. Это может быть (ab) использовано для эффективного создания предметно-ориентированных языков с новыми ключевыми словами и поведением.

Один из моих любимых примеров - метод Саймона Тэтхэма реализации сопрограмм на C с помощью макросов. Самый простой реализованный макрос:

#define crBegin static int state=0; switch(state) { case 0:

Да, с несоответствующей фигурной скобкой. Это исправят другие макросы.

4
ответ дан 7 November 2019 в 12:06
поделиться

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

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

#define MY_MAGIC_NUM 57

/*MY_MAGIC_NUM used all through out the code*/
6
ответ дан 7 November 2019 в 12:06
поделиться

sed / Java

Версия sed с 30 символами или 21 символами, если вы не включаете вызов команда: экземпляр реализации AES Брайана Гладмана http://www.gladman.me.uk/cryptography_technology/index.php )

1
ответ дан 7 November 2019 в 12:06
поделиться

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

1
ответ дан 7 November 2019 в 12:06
поделиться

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

Аналогичный случай - когда у вас есть код сборки для одной конкретной системы, а код C - для других систем.

1
ответ дан 7 November 2019 в 12:06
поделиться

В макросах код функции вставляется в поток кода вызывающей стороны. Это может, в зависимости от многих других факторов, повысить производительность, поскольку оптимизатор может процедурно интегрировать вызываемый код - оптимизировать вызываемый код в вызывающей стороне Но будьте осторожны, потому что в макросах типы аргументов не проверяются. Хорошая ссылка на встроенные функции (если вы также используете C ++) и немного макросов. http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.5

0
ответ дан 7 November 2019 в 12:06
поделиться

Это не совсем поиск и замена, это расширение токена. Макросы C - это то же самое, что и любой другой вид макроса в мире вычислений: способ написать что-то короткое и простое и автоматически превратить это во что-то более длинное и сложное.

Одна из причин использования макросов - это производительность. Это способ устранения накладных расходов на вызов функций, поскольку они всегда раскрываются в строке, в отличие от ключевого слова inline, которое часто игнорируется подсказкой компилятору и даже не существует (в стандарт) до C99. Например, см. Семейство макросов FD_, используемых вместе с fd_sets, используемыми select и pselect. Эти fd_sets на самом деле являются просто битовыми наборами, а макросы FD_ скрывают операции тиддлинга битов. Было бы неприятно каждый раз записывать бит, вращающий себя, и вызов функции был бы большим накладным расходом для такой быстрой операции, если бы она не была встроена.

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

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Еще одна вещь, которую она может сделать, чего функция не могла, - это преобразовать информацию времени компиляции в информацию времени выполнения:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

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

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

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Еще одна вещь, которую она может сделать, чего функция не могла, - это преобразовать информацию времени компиляции в информацию времени выполнения:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

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

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

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Еще одна вещь, которую она может сделать, чего функция не могла, - это преобразовать информацию времени компиляции в информацию времени выполнения:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

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

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Еще одна вещь, которую она может сделать, чего не могла сделать функция, - это преобразовать информацию времени компиляции в информацию времени выполнения:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

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

#define DEF_PAIR_OF(dtype) \
  typedef struct pair_of_##dtype { \
       dtype first; \
       dtype second; \
  } pair_of_##dtype##_t 

 DEF_PAIR_OF(int);
 DEF_PAIR_OF(double);
 DEF_PAIR_OF(MyStruct);
 /* etc */

Еще одна вещь, которую она может сделать, чего не могла сделать функция, - это превратить информацию времени компиляции в информацию времени выполнения:

#ifdef DEBUG
#define REPORT_PTR_VALUE(v) printf("Pointer %s points to %p\n", #v, v)
#else 
#define REPORT_PTR_VALUE(v)
#endif

void someFunction(const int* reallyCoolPointer) {
  REPORT_PTR_VALUE(reallyCoolPointer);
  /* Other code */
}

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

65
ответ дан 7 November 2019 в 12:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: