Для чего макросов C полезны?

Приведенный вами пример должен быть из более ранней версии Angular. В Angular 7 вы бы сделали это следующим образом:

в app.module.ts:

import { HttpClientModule } from '@angular/common/http';

и в @NgModule: imports: [ HttpClientModule ]

затем в вашем компоненте: import { HttpClient, HttpHeaders } from '@angular/common/http';

забудьте о карте, HttpClient использует общие вызовы и публикует правильный тип:

this.http.get<Person[]>('url', options).subscribe(persons => this.persons = persons /* ... */);

72
задан PointerToConstantChar 17 March 2017 в 00:10
поделиться

11 ответов

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

, Который, кажется, отражается плохо над именованием макросов. Я предположил бы, что Вы не должны будете эмулировать препроцессор, если бы это было log_function_entry() макрос.

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

Обычно они должны быть, если они не должны воздействовать на универсальные параметры.

#define max(a,b) ((a)<(b)?(b):(a))

будет работать над любым типом с < оператор.

[еще 1112], который просто функционирует, макросы позволили Вам выполнить операции с помощью символов в исходном файле. Это означает, что можно создать новое имя переменной или сослаться на исходный файл и номер строки, макрос идет.

В C99, макросы также позволяют Вам вызывать функции variadic, такие как printf

#define log_message(guard,format,...) \
   if (guard) printf("%s:%d: " format "\n", __FILE__, __LINE__,__VA_ARGS_);

log_message( foo == 7, "x %d", x)

, В котором формат работает как printf. Если защита верна, она производит сообщение наряду с номером документа и номером строки, который распечатал сообщение. Если бы это был вызов функции, то это не знало бы файл и строку, от которой Вы назвали его, и использование vaprintf будет немного большим количеством работы.

54
ответ дан Chris Maes 24 November 2019 в 12:37
поделиться

В то время как я не большой поклонник макросов и не склонен писать много C больше, на основе моего текущего управления задачами, что-то вроде этого (который мог, очевидно, иметь некоторые побочные эффекты), удобно:

#define MIN(X, Y)  ((X) < (Y) ? (X) : (Y))

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

0
ответ дан itsmatt 24 November 2019 в 12:37
поделиться

Макросы.. поскольку, когда Ваш & # (* $ & компилятор просто отказывается встраивать что-то.

, Который должен быть мотивационным плакатом, нет?

Во всей серьезности, Google злоупотребление препроцессора (можно видеть подобное ТАК вопрос как результат № 1). Если я пишу макрос, который идет вне функциональности, утверждают (), я обычно пытаюсь видеть, встроил ли мой компилятор на самом деле подобную функцию.

Другие приведут доводы против использования #if для условной компиляции.. они быть бы Вы:

if (RUNNING_ON_VALGRIND)

, а не

#if RUNNING_ON_VALGRIND

.. для отладки целей, так как Вы видите если (), но не #if в отладчике. Тогда мы погружаемся в #ifdef по сравнению с #if.

, Если в соответствии с 10 строками кода, попытайтесь встроить его. Если это не может быть встроено, попытайтесь оптимизировать его. Если его слишком глупое, чтобы быть функцией, сделайте макрос.

0
ответ дан Tim Post 24 November 2019 в 12:37
поделиться

Одна из очевидных причин - то, что при помощи макроса, код будет расширен во время компиляции, и Вы получаете псевдо вызов функции без вызова наверху.

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

1
ответ дан sykora 24 November 2019 в 12:37
поделиться

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

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

4
ответ дан Charles E. Grant 24 November 2019 в 12:37
поделиться

Это хорошо для встраивания кода и предотвращения вызова функции наверху. А также использование его, если Вы хотите изменить поведение позже, не редактируя много мест. Это не полезно для сложных вещей, но для простых строк кода, которые Вы хотите встроить, это не плохо.

3
ответ дан Peter Mortensen 24 November 2019 в 12:37
поделиться

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

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

5
ответ дан Julien Roncaglia 24 November 2019 в 12:37
поделиться

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

макросы Препроцессора на самом деле предлагают полный по Тьюрингу язык, выполняемый во время компиляции. Один из впечатляющих (и немного страшный) примеры этого закончен на стороне C++: библиотека Boost Preprocessor использует C99 / C++ 98 препроцессор для создания (относительно) безопасных конструкций программирования, которые тогда расширены до любых базовых объявлений и кодируют Вас вход, или C или C++.

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

8
ответ дан Pontus Gagge 24 November 2019 в 12:37
поделиться

Помните, что макросы (и препроцессор) прибывают с самых ранних дней C. Они раньше были ЕДИНСТВЕННЫМ способом сделать встроенные 'функции' (потому что, конечно, встроенный очень недавнее ключевое слово), и они - все еще единственный способ ВЫНУДИТЬ что-то быть встроенным.

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

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

11
ответ дан Michael Kohne 24 November 2019 в 12:37
поделиться

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

скопированный с DigitalMars.com

Обратный, когда C был изобретен, технология компилятора была примитивна. Установка текстового препроцессора макроса на фронтэнд была простым и простым способом добавить много мощных опций. Увеличивающийся размер & сложность программ проиллюстрировала, что эти функции идут со многими свойственными проблемами. D не имеет препроцессора; но D обеспечивает более масштабируемое средство решить те же проблемы.

Макросы

макросы Препроцессора добавляют мощные опции и гибкость к [1 113]. Но у них есть оборотная сторона:

  • Макросы не имеют никакого понятия объема; они допустимы от точки определения до конца источника. Они сокращают ряд через.h файлы, вложенный код, и т.д. Когда #include 'десятки тысяч луга строк макроопределений, это становится проблематичным для предотвращения непреднамеренных макрорасширений.
  • Макросы неизвестны отладчику. Попытку отладить программу с символьными данными подрывает отладчик, только зная о макрорасширениях, не макросах самих.
  • Макросы лишают возможности маркировать исходный код, поскольку более раннее макро-изменение может произвольно восстановить маркеры.
  • чисто текстовое основание макросов приводит к произвольному и непоследовательному использованию, делая код с помощью подверженных ошибкам макросов. (Некоторая попытка разрешить это была начата с шаблонов в [1 115].)
  • Макросы все еще используются для восполнения дефицитов в выразительной возможности языка, такой что касается "оберток" вокруг заголовочных файлов.

Вот перечисление общего использования для макросов и соответствующая функция в D:

  1. Определяющие литеральные константы:

    • C Препроцессор Путь

      #define VALUE 5
      
    • D Путь

      const int VALUE = 5;
      
  2. Создание списка значений или флагов:

    • C Препроцессор Путь

      int flags:
      #define FLAG_X  0x1
      #define FLAG_Y  0x2
      #define FLAG_Z  0x4
      ...
      flags |= FLAG_X;
      
    • D Путь

      enum FLAGS { X = 0x1, Y = 0x2, Z = 0x4 };
      FLAGS flags;
      ...
      flags |= FLAGS.X;
      
  3. соглашения о вызовах функции Установки:

    • C Препроцессор Путь

      #ifndef _CRTAPI1
      #define _CRTAPI1 __cdecl
      #endif
      #ifndef _CRTAPI2
      #define _CRTAPI2 __cdecl
      #endif
      
      int _CRTAPI2 func();
      
    • D Путь

      Соглашения о вызовах могут быть определены в блоках, таким образом, нет никакой потребности изменить его для каждой функции:

      extern (Windows)
      {
          int onefunc();
          int anotherfunc();
      }
      
  4. Простое универсальное программирование:

    • C Препроцессор Путь

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

      #ifdef UNICODE
      int getValueW(wchar_t *p);
      #define getValue getValueW
      #else
      int getValueA(char *p);
      #define getValue getValueA
      #endif
      
    • D Путь

      D включает объявления символов, которые являются псевдонимами других символов:

      version (UNICODE)
      {
          int getValueW(wchar[] p);
          alias getValueW getValue;
      }
      else
      {
          int getValueA(char[] p);
          alias getValueA getValue;
      }
      

существует больше примеров на веб-сайт DigitalMars .

17
ответ дан Brad Gilbert 24 November 2019 в 12:37
поделиться

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

Они также очень полезны для написания "функционально-подобных" выражений, которые являются "полиморфными" или "перегруженными"; например, макрос max, определенный как:

#define max(a,b) ((a)>(b)?(a):(b))

, полезен для любого числового типа; а в C вы не можете писать:

int max(int a, int b) {return a>b?a:b;}
float max(float a, float b) {return a>b?a:b;}
double max(double a, double b) {return a>b?a:b;}
...

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

И не говоря уже об условной компиляции и включении файлов (которые также являются частью макроязыка) ...

15
ответ дан 24 November 2019 в 12:37
поделиться
Другие вопросы по тегам:

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