Какие #pragma
примеры использования C в C?
Какие #pragma
примеры использования C в C?
Ответы:
#pragma
предназначен для директив компилятора, которые зависят от машины или операционной системы, то есть он сообщает компилятору, что нужно что-то сделать, установить какой-то параметр, предпринять какое-то действие, переопределить какое-то значение по умолчанию и т. д., которые могут или не могут применяться ко всем машинам и рабочим системы.
См. Msdn для получения дополнительной информации.
#pragma
используется, чтобы делать что-то специфичное для реализации в C, т.е. быть прагматичным для текущего контекста, а не идеологически догматичным.
Я регулярно использую тот, #pragma pack(1)
где я пытаюсь выжать больше из своего пространства памяти на встроенных решениях с массивами структур, которые в противном случае закончились бы 8-байтовым выравниванием.
Жалко, что у нас #dogma
еще нет. Было бы весело;)
pragma(1)
Скорость тоже реально не улучшает? См stackoverflow.com/questions/3318410/...
Обычно я бы старался избегать использования #pragmas, если это возможно, поскольку они сильно зависят от компилятора и не переносятся. Если вы хотите использовать их в портативном режиме, вам придется окружить каждую прагму парой #if
/ #endif
. GCC не рекомендует использовать прагмы и поддерживает только некоторые из них для совместимости с другими компиляторами; У GCC есть другие способы делать те же вещи, для которых другие компиляторы используют прагмы.
Например, вот как вы можете убедиться, что структура плотно упакована (т.е. без заполнения между членами) в MSVC:
#pragma pack(push, 1)
struct PackedStructure
{
char a;
int b;
short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7
Вот как бы вы сделали то же самое в GCC:
struct PackedStructure __attribute__((__packed__))
{
char a;
int b;
short c;
};
// sizeof(PackedStructure == 7)
Код GCC более переносим, потому что если вы хотите скомпилировать его с помощью компилятора, отличного от GCC, все, что вам нужно сделать, это
#define __attribute__(x)
Если вы хотите перенести код MSVC, вы должны окружить каждую прагму парой #if
/ #endif
. Не очень.
struct __attribute__((__packed__)) PackedStructure
hack
когда встречает прагму, которую не распознает, как это было когда-то очень, очень давно - см. #pragma
GCC и т. Д.)
Размещение #pragma once
в верхней части файла заголовка гарантирует, что он будет включен только один раз. Обратите внимание, что #pragma once
это не стандартный C99, но поддерживается большинством современных компиляторов.
Альтернативой является использование включенных охранников (например #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */
)
то, что я чувствую, #pragma
это директива, в которой, если вы хотите, чтобы код был специфичным для местоположения. скажите ситуацию, когда вы хотите, чтобы счетчик программы читал с определенного адреса, по которому написана ISR, тогда вы можете указать ISR в этом месте, используя #pragma vector=ADC12_VECTOR
и следуя название прерывания и его описание
Мой лучший совет - взглянуть на документацию вашего компилятора, потому что прагмы по определению зависят от реализации. Например, во встроенных проектах я использовал их для размещения кода и данных в разных разделах или для объявления обработчиков прерываний. то есть:
#pragma code BANK1
#pragma data BANK2
#pragma INT3 TimerHandler
Все ответы выше хорошо объясняют, #pragma
но я хотел добавить небольшой пример
Я просто хочу объяснить simple OpenMP example
, как можно использовать #pragma
его для работы.
OpenMp
briefly
- это реализация для многоплатформенного параллельного программирования с общей памятью (тогда мы можем сказать, что этоmachine-specific
илиoperating-system-specific
)
перейдем к примеру
#include <stdio.h>
#include <omp.h>// compile with: /openmp
int main() {
#pragma omp parallel num_threads(4)
{
int i = omp_get_thread_num();
printf_s("Hello from thread %d\n", i);
}
}
выход
Hello from thread 0
Hello from thread 1
Hello from thread 2
Hello from thread 3
Note that the order of output can vary on different machines.
теперь позвольте мне рассказать вам, что #pragma
сделал ...
он сообщает ОС запустить некоторый блок кода в 4 потоках
это только один из many many applications
вас, который может сделать с маленьким#pragma
извините за внешний образец OpenMP
Это директива препроцессора, которую можно использовать для включения или выключения определенных функций.
Он бывает двух типов #pragma startup
, #pragma exit
и #pragma warn
.
#pragma startup
позволяет нам определять функции, вызываемые при запуске программы.
#pragma exit
позволяет нам указывать функции, вызываемые при выходе из программы.
#pragma warn
сообщает компьютеру подавить любое предупреждение или нет.
Многие другие #pragma
стили можно использовать для управления компилятором.
#pragma startup
- это директива, которая используется для вызова функции перед основной функцией и для вызова другой функции после основной функции, например
#pragma startup func1
#pragma exit func2
Здесь func1
выполняется до main
и func2
после.
ПРИМЕЧАНИЕ. Этот код работает только в компиляторе Turbo-C. Для достижения этой функциональности в GCC, вы можете объявить func1
и func2
как это:
void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Подводя итог, #pragma
говорит компилятору что-то делать. Вот несколько способов его использования:
#pragma
может использоваться для игнорирования предупреждений компилятора. Например, чтобы заставить GCC замолчать о неявных объявлениях функций, вы можете написать:
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
Более старая версия libportable
делает это переносимо .
#pragma once
при записи в верхней части файла заголовка приведет к однократному включению указанного файла заголовка. libportable
проверяет наличие прагмы после поддержки.
#pragma
Директива переживает стадию предварительной обработки. В отличие от#include
и#define
.