@smwikipedia, você quer dizer que alguns pragmas sobrevivem? #pragma once é uma diretiva de pré-processador, mas #pragma pack é uma diretiva de compilador
Lewis Kelsey
Respostas:
66
#pragma é para diretivas de compilador que são específicas da máquina ou do sistema operacional, ou seja, diz ao compilador para fazer algo, definir alguma opção, executar alguma ação, substituir algum padrão, etc. que pode ou não se aplicar a todas as máquinas e operação sistemas.
"isso pode ou não se aplicar a todas as máquinas e sistemas operacionais." - e diferentes compiladores na mesma máquina. E o que pode significar coisas diferentes em compiladores diferentes.
Steve Jessop,
53
#pragma é usado para fazer algo específico de implementação em C, ou seja, ser pragmático para o contexto atual ao invés de ideologicamente dogmático.
O que eu uso regularmente é #pragma pack(1)onde estou tentando espremer mais do meu espaço de memória em soluções incorporadas, com matrizes de estruturas que, de outra forma, terminariam com alinhamento de 8 bytes.
Pena que ainda não temos #dogma. Isso seria divertido ;)
@Pacerier, normalmente não. De acordo com os comentários do jalfs, os dados alinhados em um limite de 4 bytes para processadores de 32 bits ou de 8 bytes para processadores de 64 bits serão normalmente carregados e armazenados em uma única operação. Os dados alinhados em limites menores exigirão várias operações para carregar ou armazenar. Isso é mais lento.
SmacL de
35
Eu geralmente tentaria evitar o uso de #pragmas, se possível, já que eles são extremamente dependentes do compilador e não portáteis. Se você quiser usá-los de forma portátil, terá que envolver cada pragma com um par #if/ #endif. O GCC desencoraja o uso de pragmas e realmente só oferece suporte a alguns deles para compatibilidade com outros compiladores; O GCC tem outras maneiras de fazer as mesmas coisas para as quais outros compiladores usam pragmas.
Por exemplo, veja como você pode garantir que uma estrutura seja compactada firmemente (ou seja, sem preenchimento entre os membros) no MSVC:
Portanto, se eu quiser compilar o código GCC no MSVC e precisar compactar a estrutura, exatamente como faço?
SmacL
2
Para gcc, é struct __attribute__((__packed__)) PackedStructure
Laurent Debricon
#pragma uma vez não é realisticamente "dependente do compilador e não portátil". É suportado em todas as principais plataformas e muitos não-principais plataformas .. en.wikipedia.org/wiki/Pragma_once#Portability
xaxxon
1
Observe que C99 e C11 contêm (C11) §6.10.6 diretivas Pragma e ¶1 Qualquer pragma que não seja reconhecido pela implementação é ignorado. Até mesmo C90 diz isso, embora estivesse na seção §6.8.6. (Isso torna o GCC não compatível se for executado hackao encontrar um pragma que não reconhece, como costumava fazer há muito, muito tempo - veja #pragmae GCC , etc.)
Jonathan Leffler
15
Colocar #pragma onceno topo do arquivo de cabeçalho garantirá que ele seja incluído apenas uma vez. Observe que #pragma oncenão é o C99 padrão, mas é compatível com a maioria dos compiladores modernos.
Uma alternativa é usar proteções de inclusão (por exemplo #ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */)
o que eu sinto é #pragmauma diretiva onde se você quiser que o código seja específico de um local. diga uma situação em que você deseja que o contador do programa leia do endereço específico onde o ISR está escrito, então você pode especificar o ISR naquele local usando #pragma vector=ADC12_VECTORe seguido por nome de rotinas de interrupção e sua descrição
Meu melhor conselho é examinar a documentação do seu compilador, porque os pragmas são, por definição, específicos da implementação. Por exemplo, em projetos incorporados, usei-os para localizar código e dados em diferentes seções ou declarar manipuladores de interrupção. ie:
#pragma code BANK1
#pragma data BANK2
#pragma INT3 TimerHandler
Todos os pragmas são específicos de implementação - exceto os pragmas #pragma STDC ..., que são padronizados em todas as plataformas (além do C99).
Jonathan Leffler
4
Todas as respostas acima são boas explicações para, #pragmamas eu queria adicionar um pequeno exemplo
Eu só quero explicar um simple OpenMP exampleque demonstra alguns usos de #pragmafazer seu trabalho
OpenMp brieflyé uma implementação para programação paralela de memória compartilhada multiplataforma (então podemos dizer que é machine-specificou operating-system-specific)
vamos ao exemplo
#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);}}
a saída é
Hello from thread 0Hello from thread 1Hello from thread 2Hello from thread 3Note that the order of output can vary on different machines.
agora deixe-me dizer o que #pragmafez ...
diz ao sistema operacional para executar algum bloco de código em 4 threads
isso é apenas um de many many applicationsvocês pode fazer com o pouco#pragma
#pragma startup é uma diretiva que é usada para chamar uma função antes da função principal e para chamar outra função após a função principal, por exemplo
#pragma startup func1
#pragma exit func2
Aqui, func1corre antes maine func2corre depois.
NOTA: Este código funciona apenas no compilador Turbo-C. Para obter essa funcionalidade no GCC, você pode declarar func1e func2assim:
Para resumir, #pragmadiz ao compilador para fazer as coisas. Aqui estão algumas maneiras de usá-lo:
#pragmapode ser usado para ignorar avisos do compilador. Por exemplo, para fazer o GCC calar a boca sobre declarações de funções implícitas, você pode escrever:
#pragma once, quando escrito no topo de um arquivo de cabeçalho, fará com que o referido arquivo de cabeçalho seja incluído uma vez. libportableverifica o pragma uma vez que o suporte.
#pragma
A diretiva sobrevive ao estágio de pré-processamento. Ao contrário de#include
e#define
.Respostas:
#pragma
é para diretivas de compilador que são específicas da máquina ou do sistema operacional, ou seja, diz ao compilador para fazer algo, definir alguma opção, executar alguma ação, substituir algum padrão, etc. que pode ou não se aplicar a todas as máquinas e operação sistemas.Veja msdn para mais informações.
fonte
#pragma
é usado para fazer algo específico de implementação em C, ou seja, ser pragmático para o contexto atual ao invés de ideologicamente dogmático.O que eu uso regularmente é
#pragma pack(1)
onde estou tentando espremer mais do meu espaço de memória em soluções incorporadas, com matrizes de estruturas que, de outra forma, terminariam com alinhamento de 8 bytes.Pena que ainda não temos
#dogma
. Isso seria divertido ;)fonte
pragma(1)
melhora a velocidade? Consulte stackoverflow.com/questions/3318410/…Eu geralmente tentaria evitar o uso de #pragmas, se possível, já que eles são extremamente dependentes do compilador e não portáteis. Se você quiser usá-los de forma portátil, terá que envolver cada pragma com um par
#if
/#endif
. O GCC desencoraja o uso de pragmas e realmente só oferece suporte a alguns deles para compatibilidade com outros compiladores; O GCC tem outras maneiras de fazer as mesmas coisas para as quais outros compiladores usam pragmas.Por exemplo, veja como você pode garantir que uma estrutura seja compactada firmemente (ou seja, sem preenchimento entre os membros) no MSVC:
Veja como você faria a mesma coisa no GCC:
O código GCC é mais portátil, porque se você quiser compilá-lo com um compilador não-GCC, tudo que você precisa fazer é
#define __attribute__(x)
Ao passo que, se você deseja portar o código MSVC, deve envolver cada pragma com um par
#if
/#endif
. Feio.fonte
struct __attribute__((__packed__)) PackedStructure
hack
ao encontrar um pragma que não reconhece, como costumava fazer há muito, muito tempo - veja#pragma
e GCC , etc.)Colocar
#pragma once
no topo do arquivo de cabeçalho garantirá que ele seja incluído apenas uma vez. Observe que#pragma once
não é o C99 padrão, mas é compatível com a maioria dos compiladores modernos.Uma alternativa é usar proteções de inclusão (por exemplo
#ifndef MY_FILE #define MY_FILE ... #endif /* MY_FILE */
)fonte
o que eu sinto é
#pragma
uma diretiva onde se você quiser que o código seja específico de um local. diga uma situação em que você deseja que o contador do programa leia do endereço específico onde o ISR está escrito, então você pode especificar o ISR naquele local usando#pragma vector=ADC12_VECTOR
e seguido por nome de rotinas de interrupção e sua descriçãofonte
Meu melhor conselho é examinar a documentação do seu compilador, porque os pragmas são, por definição, específicos da implementação. Por exemplo, em projetos incorporados, usei-os para localizar código e dados em diferentes seções ou declarar manipuladores de interrupção. ie:
fonte
Todas as respostas acima são boas explicações para,
#pragma
mas eu queria adicionar um pequeno exemploEu só quero explicar um
simple OpenMP example
que demonstra alguns usos de#pragma
fazer seu trabalhovamos ao exemplo
a saída é
agora deixe-me dizer o que
#pragma
fez ...diz ao sistema operacional para executar algum bloco de código em 4 threads
isso é apenas um de
many many applications
vocês pode fazer com o pouco#pragma
desculpe pela amostra externa
OpenMP
fonte
Esta é uma diretiva de pré-processador que pode ser usada para ligar ou desligar certos recursos.
É de dois tipos
#pragma startup
,#pragma exit
e#pragma warn
.#pragma startup
nos permite especificar funções chamadas na inicialização do programa.#pragma exit
nos permite especificar funções chamadas na saída do programa.#pragma warn
diz ao computador para suprimir qualquer aviso ou não.Muitos outros
#pragma
estilos podem ser usados para controlar o compilador.fonte
#pragma startup
é uma diretiva que é usada para chamar uma função antes da função principal e para chamar outra função após a função principal, por exemploAqui,
func1
corre antesmain
efunc2
corre depois.NOTA: Este código funciona apenas no compilador Turbo-C. Para obter essa funcionalidade no GCC, você pode declarar
func1
efunc2
assim:fonte
Para resumir,
#pragma
diz ao compilador para fazer as coisas. Aqui estão algumas maneiras de usá-lo:#pragma
pode ser usado para ignorar avisos do compilador. Por exemplo, para fazer o GCC calar a boca sobre declarações de funções implícitas, você pode escrever:Uma versão mais antiga do
libportable
faz isso portavelmente .#pragma once
, quando escrito no topo de um arquivo de cabeçalho, fará com que o referido arquivo de cabeçalho seja incluído uma vez.libportable
verifica o pragma uma vez que o suporte.fonte