@smwikipedia masz na myśli przetrwanie niektórych pragm? #pragma kiedyś jest dyrektywą preprocesora, ale #pragma pack to dyrektywa kompilatora
Lewis Kelsey
Odpowiedzi:
66
#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.
„to może, ale nie musi dotyczyć wszystkich komputerów i systemów operacyjnych”. - i różne kompilatory na tej samej maszynie. A co może oznaczać różne rzeczy na różnych kompilatorach.
Steve Jessop,
53
#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 ;)
@Pacerier, zazwyczaj nie. Zgodnie z komentarzami jalfs, dane, które są wyrównane do 4-bajtowej granicy dla procesorów 32-bitowych lub 8-bajtowej dla procesorów 64-bitowych, będą zazwyczaj ładowane i przechowywane w ramach jednej operacji. Dane, które są wyrównane na mniejszych granicach, będą wymagały wielu operacji, aby załadować lub zapisać. To jest wolniejsze.
SmacL
35
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:
Więc jeśli chcę skompilować kod GCC na MSVC i muszę spakować strukturę, jak dokładnie mam to zrobić?
SmacL
2
Dla gcc jest to struct __attribute__((__packed__)) PackedStructure
Laurent Debricon
#pragma raz nie jest realistycznie „zależna od kompilatora i nieprzenośna”. Jest obsługiwany na każdej większej platformie i wielu
mniejszych
1
Zauważ, że oba C99 i C11 zawierają (C11) §6.10.6 dyrektywy Pragmy, a ¶1. Każda taka pragma, która nie jest rozpoznawana przez implementację, jest ignorowana. Nawet C90 tak mówi, chociaż było to w sekcji §6.8.6. (To sprawia, że GCC jest niezgodne, jeśli działa, hackgdy napotyka pragmę, której nie rozpoznaje, jak to miało miejsce kiedyś, bardzo, bardzo dawno temu - zobacz #pragmai GCC itp.)
Jonathan Leffler
15
Umieszczenie #pragma oncena górze pliku nagłówkowego zapewni, że zostanie on uwzględniony tylko raz. Zauważ, że #pragma oncenie 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 #pragmato 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_VECTORi 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 pragmy są specyficzne dla implementacji - z wyjątkiem pragm #pragma STDC ..., które są ujednolicone na wszystkich platformach (dodatek do C99).
Jonathan Leffler
4
Wszystkie powyższe odpowiedzi stanowią miłe wyjaśnienia, #pragmaale chciałem dodać mały przykład
Chcę tylko wyjaśnić, simple OpenMP exampleco pokazuje niektóre zastosowania programu #pragmado wykonywania jego pracy
OpenMP brieflyto implementacja dla wielu platform programowania równoległego wspólną pamięcią (wtedy możemy powiedzieć, że jest machine-specificlub operating-system-specific)
przejdźmy do przykładu
#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);}}
wyjście jest
Hello from thread 0Hello from thread 1Hello from thread 2Hello from thread 3Note that the order of output can vary on different machines.
teraz powiem ci, co #pragmazrobiło ...
mówi systemowi operacyjnemu, aby uruchomił jakiś blok kodu w 4 wątkach
to tylko jedna z many many applicationsrzeczy, które możesz zrobić z małym#pragma
#pragma
Dyrektywa przetrwa etap wstępnego przetwarzania. W przeciwieństwie do#include
i#define
.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.Aby uzyskać więcej informacji, zobacz msdn .
źródło
#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 ;)źródło
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:
Oto jak zrobiłbyś to samo w GCC:
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.źródło
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 */
)źródło
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źródło
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:
źródło
Wszystkie powyższe odpowiedzi stanowią miłe wyjaśnienia,
#pragma
ale chciałem dodać mały przykładChcę tylko wyjaśnić,
simple OpenMP example
co pokazuje niektóre zastosowania programu#pragma
do wykonywania jego pracyprzejdźmy do przykładu
wyjście jest
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
źródło
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.źródło
#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, npTutaj
func1
biegnie przedmain
ifunc2
biegnie później.UWAGA: Ten kod działa tylko w kompilatorze Turbo-C. Aby osiągnąć tę funkcjonalność w GCC, możesz zadeklarować
func1
ifunc2
tak:źródło
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ć: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.źródło