@smwikipedia, вы имеете в виду, что некоторые прагмы выживают? #pragma once - это директива препроцессора, но #pragma pack - это директива компилятора
Льюис Келси,
Ответы:
66
#pragma предназначен для директив компилятора, которые зависят от машины или операционной системы, то есть он сообщает компилятору, что нужно что-то сделать, установить какой-то параметр, предпринять какое-то действие, переопределить какое-то значение по умолчанию и т. д., которые могут или не могут применяться ко всем машинам и рабочим системы.
«это может или не может применяться ко всем машинам и операционным системам». - и разные компиляторы на одной машине. И это может означать разные вещи в разных компиляторах.
Стив Джессоп,
53
#pragma используется, чтобы делать что-то специфичное для реализации в C, т.е. быть прагматичным для текущего контекста, а не идеологически догматичным.
Я регулярно использую тот, #pragma pack(1)где я пытаюсь выжать больше из своего пространства памяти на встроенных решениях с массивами структур, которые в противном случае закончились бы 8-байтовым выравниванием.
@Pacerier, как правило, нет. Согласно комментариям jalfs, данные, которые выровнены по 4-байтовой границе для 32-битных процессоров или 8-байтовой границе для 64-битных процессоров, обычно загружаются и сохраняются за одну операцию. Данные, которые выровнены по меньшим границам, потребуют нескольких операций для загрузки или сохранения. Это медленнее.
SmacL
35
Обычно я бы старался избегать использования #pragmas, если это возможно, поскольку они сильно зависят от компилятора и не переносятся. Если вы хотите использовать их в портативном режиме, вам придется окружить каждую прагму парой #if/ #endif. GCC не рекомендует использовать прагмы и поддерживает только некоторые из них для совместимости с другими компиляторами; У GCC есть другие способы делать те же вещи, для которых другие компиляторы используют прагмы.
Например, вот как вы можете убедиться, что структура плотно упакована (т.е. без заполнения между членами) в MSVC:
Итак, если я хочу скомпилировать код GCC на MSVC и мне нужно упаковать структуру, как именно мне это сделать?
SmacL 06
2
Для gcc это struct __attribute__((__packed__)) PackedStructure
Лоран Дебрикон
#pragma once не реально "зависит от компилятора и не переносится". Он поддерживается на всех основных платформах и на многих
неосновных
1
Обратите внимание, что C99 и C11 оба содержат (C11) §6.10.6 директивы Pragma и ¶1. Любая такая прагма, которая не распознается реализацией, игнорируется. Даже C90 говорит это, хотя это было в разделе §6.8.6. (Это делает GCC несовместимым, если он запускается, hackкогда встречает прагму, которую не распознает, как это было когда-то очень, очень давно - см. #pragmaGCC и т. Д.)
Джонатан Леффлер,
15
Размещение #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 STDC ..., которые стандартизированы для всех платформ (в дополнение к C99).
Джонатан Леффлер,
4
Все ответы выше хорошо объясняют, #pragmaно я хотел добавить небольшой пример
Я просто хочу объяснить simple OpenMP example, как можно использовать #pragmaего для работы.
OpenMp briefly- это реализация для многоплатформенного параллельного программирования с общей памятью (тогда мы можем сказать, что это machine-specificили operating-system-specific)
перейдем к примеру
#include<stdio.h>#include<omp.h>// compile with: /openmpint main(){#pragma omp parallel num_threads(4){int i = omp_get_thread_num();
printf_s("Hello from thread %d\n", i);}}
выход
Hello from thread 0Hello from thread 1Hello from thread 2Hello from thread 3Note that the order of output can vary on different machines.
теперь позвольте мне рассказать вам, что #pragmaсделал ...
он сообщает ОС запустить некоторый блок кода в 4 потоках
это только один из many many applicationsвас, который может сделать с маленьким#pragma
#pragma startup - это директива, которая используется для вызова функции перед основной функцией и для вызова другой функции после основной функции, например
#pragma startup func1
#pragma exit func2
Здесь func1выполняется до mainи func2после.
ПРИМЕЧАНИЕ. Этот код работает только в компиляторе Turbo-C. Для достижения этой функциональности в GCC, вы можете объявить func1и func2как это:
Подводя итог, #pragmaговорит компилятору что-то делать. Вот несколько способов его использования:
#pragmaможет использоваться для игнорирования предупреждений компилятора. Например, чтобы заставить GCC замолчать о неявных объявлениях функций, вы можете написать:
#pragma onceпри записи в верхней части файла заголовка приведет к однократному включению указанного файла заголовка. libportableпроверяет наличие прагмы после поддержки.
#pragma
Директива переживает стадию предварительной обработки. В отличие от#include
и#define
.Ответы:
#pragma
предназначен для директив компилятора, которые зависят от машины или операционной системы, то есть он сообщает компилятору, что нужно что-то сделать, установить какой-то параметр, предпринять какое-то действие, переопределить какое-то значение по умолчанию и т. д., которые могут или не могут применяться ко всем машинам и рабочим системы.См. Msdn для получения дополнительной информации.
источник
#pragma
используется, чтобы делать что-то специфичное для реализации в C, т.е. быть прагматичным для текущего контекста, а не идеологически догматичным.Я регулярно использую тот,
#pragma pack(1)
где я пытаюсь выжать больше из своего пространства памяти на встроенных решениях с массивами структур, которые в противном случае закончились бы 8-байтовым выравниванием.Жалко, что у нас
#dogma
еще нет. Было бы весело;)источник
pragma(1)
Скорость тоже реально не улучшает? См stackoverflow.com/questions/3318410/...Обычно я бы старался избегать использования #pragmas, если это возможно, поскольку они сильно зависят от компилятора и не переносятся. Если вы хотите использовать их в портативном режиме, вам придется окружить каждую прагму парой
#if
/#endif
. GCC не рекомендует использовать прагмы и поддерживает только некоторые из них для совместимости с другими компиляторами; У GCC есть другие способы делать те же вещи, для которых другие компиляторы используют прагмы.Например, вот как вы можете убедиться, что структура плотно упакована (т.е. без заполнения между членами) в MSVC:
Вот как бы вы сделали то же самое в GCC:
Код 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
но я хотел добавить небольшой примерЯ просто хочу объяснить
simple OpenMP example
, как можно использовать#pragma
его для работы.перейдем к примеру
выход
теперь позвольте мне рассказать вам, что
#pragma
сделал ...он сообщает ОС запустить некоторый блок кода в 4 потоках
это только один из
many many applications
вас, который может сделать с маленьким#pragma
извините за внешний образец
OpenMP
источник
Это директива препроцессора, которую можно использовать для включения или выключения определенных функций.
Он бывает двух типов
#pragma startup
,#pragma exit
и#pragma warn
.#pragma startup
позволяет нам определять функции, вызываемые при запуске программы.#pragma exit
позволяет нам указывать функции, вызываемые при выходе из программы.#pragma warn
сообщает компьютеру подавить любое предупреждение или нет.Многие другие
#pragma
стили можно использовать для управления компилятором.источник
#pragma startup
- это директива, которая используется для вызова функции перед основной функцией и для вызова другой функции после основной функции, напримерЗдесь
func1
выполняется доmain
иfunc2
после.ПРИМЕЧАНИЕ. Этот код работает только в компиляторе Turbo-C. Для достижения этой функциональности в GCC, вы можете объявить
func1
иfunc2
как это:источник
Подводя итог,
#pragma
говорит компилятору что-то делать. Вот несколько способов его использования:#pragma
может использоваться для игнорирования предупреждений компилятора. Например, чтобы заставить GCC замолчать о неявных объявлениях функций, вы можете написать:Более старая версия
libportable
делает это переносимо .#pragma once
при записи в верхней части файла заголовка приведет к однократному включению указанного файла заголовка.libportable
проверяет наличие прагмы после поддержки.источник