Jakie są zastosowania #pragma
w języku C wraz z przykładami?
Jakie są zastosowania #pragma
w języku C wraz z przykładami?
Odpowiedzi:
#pragma
jest przeznaczony dla dyrektyw kompilatora, które są specyficzne dla maszyny lub systemu operacyjnego, tj. mówi kompilatorowi, aby coś zrobił, ustawił jakąś opcję, wykonał jakąś akcję, nadpisał niektóre domyślne itp., które mogą, ale nie muszą dotyczyć wszystkich maszyn i działających systemy.
#pragma
jest używany do zrobienia czegoś specyficznego dla implementacji w C, tj. jest pragmatyczny w obecnym kontekście, a nie ideologicznie dogmatyczny.
Ten, którego regularnie używam, polega na #pragma pack(1)
tym, że staram się wycisnąć więcej z mojej pamięci w rozwiązaniach osadzonych, z tablicami struktur, które w przeciwnym razie zakończyłyby się wyrównaniem 8 bajtów.
Szkoda, że jeszcze nie mamy #dogma
. To byłoby fajne ;)
pragma(1)
poprawia szybkości? Zobacz stackoverflow.com/questions/3318410/…
Generalnie starałbym się unikać używania #pragmas, jeśli to możliwe, ponieważ są one bardzo zależne od kompilatora i nieprzenośne. Jeśli chcesz używać ich w sposób przenośny, musisz otoczyć każdą pragmę parą #if
/ #endif
. GCC odradza używanie pragm i tak naprawdę obsługuje tylko niektóre z nich w celu zapewnienia zgodności z innymi kompilatorami; GCC ma inne sposoby robienia tych samych rzeczy, do których inne kompilatory używają pragm.
Na przykład, oto jak upewnić się, że struktura jest ciasno upakowana (tj. Bez dopełnienia między elementami) w MSVC:
#pragma pack(push, 1)
struct PackedStructure
{
char a;
int b;
short c;
};
#pragma pack(pop)
// sizeof(PackedStructure) == 7
Oto jak zrobiłbyś to samo w GCC:
struct PackedStructure __attribute__((__packed__))
{
char a;
int b;
short c;
};
// sizeof(PackedStructure == 7)
Kod GCC jest bardziej przenośny, ponieważ jeśli chcesz skompilować go za pomocą kompilatora innego niż GCC, wszystko, co musisz zrobić, to
#define __attribute__(x)
Natomiast jeśli chcesz przenieść kod MSVC, musisz otoczyć każdą pragmę za pomocą #if
/ #endif
pair. Niezbyt ładne.
struct __attribute__((__packed__)) PackedStructure
hack
gdy napotyka pragmę, której nie rozpoznaje, jak to miało miejsce kiedyś, bardzo, bardzo dawno temu - zobacz #pragma
i GCC itp.)
Umieszczenie #pragma once
na górze pliku nagłówkowego zapewni, że zostanie on uwzględniony tylko raz. Zauważ, że #pragma once
nie jest to standardowe C99, ale obsługiwane przez większość nowoczesnych kompilatorów.
Alternatywą jest użycie osłon (np. #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */
)
czuję, że jest #pragma
to dyrektywa, w której jeśli chcesz, aby kod był specyficzny dla lokalizacji. powiedz sytuację, w której chcesz, aby licznik programu czytał z określonego adresu, pod którym jest zapisany ISR, możesz określić ISR w tej lokalizacji za pomocą #pragma vector=ADC12_VECTOR
i następnie przerwać rotines nazwa i jej opis
Moją najlepszą radą jest przyjrzenie się dokumentacji kompilatora, ponieważ pragmy są z definicji specyficzne dla implementacji. Na przykład w projektach osadzonych używałem ich do lokalizowania kodu i danych w różnych sekcjach lub deklarowania programów obsługi przerwań. to znaczy:
#pragma code BANK1
#pragma data BANK2
#pragma INT3 TimerHandler
Wszystkie powyższe odpowiedzi stanowią miłe wyjaśnienia, #pragma
ale chciałem dodać mały przykład
Chcę tylko wyjaśnić, simple OpenMP example
co pokazuje niektóre zastosowania programu #pragma
do wykonywania jego pracy
OpenMP
briefly
to implementacja dla wielu platform programowania równoległego wspólną pamięcią (wtedy możemy powiedzieć, że jestmachine-specific
luboperating-system-specific
)
przejdźmy do przykładu
#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);
}
}
wyjście jest
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.
teraz powiem ci, co #pragma
zrobiło ...
mówi systemowi operacyjnemu, aby uruchomił jakiś blok kodu w 4 wątkach
to tylko jedna z many many applications
rzeczy, które możesz zrobić z małym#pragma
przepraszam za zewnętrzną próbkę OpenMP
Jest to dyrektywa preprocesora, której można używać do włączania lub wyłączania niektórych funkcji.
Jest dwóch typów #pragma startup
, #pragma exit
i #pragma warn
.
#pragma startup
pozwala nam określić funkcje wywoływane podczas uruchamiania programu.
#pragma exit
pozwala nam określić funkcje wywoływane po zakończeniu programu.
#pragma warn
informuje komputer, aby pominął wszelkie ostrzeżenia lub nie.
Do #pragma
sterowania kompilatorem można użyć wielu innych stylów.
#pragma startup
to dyrektywa, która jest używana do wywołania funkcji przed funkcją główną i do wywołania innej funkcji po funkcji głównej, np
#pragma startup func1
#pragma exit func2
Tutaj func1
biegnie przed main
i func2
biegnie później.
UWAGA: Ten kod działa tylko w kompilatorze Turbo-C. Aby osiągnąć tę funkcjonalność w GCC, możesz zadeklarować func1
i func2
tak:
void __attribute__((constructor)) func1();
void __attribute__((destructor)) func2();
Podsumowując, #pragma
mówi kompilatorowi, aby coś zrobił. Oto kilka sposobów, w jakie go używam:
#pragma
może służyć do ignorowania ostrzeżeń kompilatora. Na przykład, aby zamknąć GCC na niejawne deklaracje funkcji, możesz napisać:
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
Starsza wersja libportable
robi to przenośnie .
#pragma once
zapisany na górze pliku nagłówkowego spowoduje jednorazowe dołączenie wspomnianego pliku nagłówkowego. libportable
sprawdza pragmę po wsparciu.
#pragma
Dyrektywa przetrwa etap wstępnego przetwarzania. W przeciwieństwie do#include
i#define
.