Eu entendo que inline
por si só é uma sugestão para o compilador e, a seu critério, ele pode ou não embutir a função e também produzir código de objeto vinculável.
Acho que static inline
faz o mesmo (pode ou não embutir), mas não produzirá código de objeto vinculável quando embutido (já que nenhum outro módulo pode ser vinculado a ele).
Onde se extern inline
encaixa na imagem?
Suponha que eu queira substituir uma macro de pré-processador por uma função embutida e exigir que essa função seja embutida (por exemplo, porque ela usa as macros __FILE__
e __LINE__
que devem ser resolvidas para o chamador, mas não para esta função chamada). Ou seja, desejo ver um erro do compilador ou do vinculador no caso de a função não ficar embutida. Faz extern inline
isso? (Presumo que, se não, não há outra maneira de atingir esse comportamento além de manter uma macro.)
Existem diferenças entre C ++ e C?
Existem diferenças entre os diferentes fornecedores e versões de compiladores?
fonte
extern inline
está sujeita a uma regra de definição e esta é a definição. Mas se as heurísticas de otimização definidas pela implementação seguirem a recomendação de usar ainline
palavra - chave como uma sugestão de que "as chamadas para a função sejam o mais rápido possível" (ISO 9899: 1999 §6.7.4 (5),extern inline
contagensEu acredito que você interpretou mal __FILE__ e __LINE__ com base nesta declaração:
Existem várias fases de compilação e o pré-processamento é a primeira. __FILE__ e __LINE__ são substituídos durante essa fase. Portanto, no momento em que o compilador pode considerar a função para inlining, eles já foram substituídos.
fonte
Parece que você está tentando escrever algo assim:
e esperando que você obtenha valores diferentes impressos a cada vez. Como Don diz, você não vai, porque __FILE__ e __LINE__ são implementados pelo pré-processador, mas em linha é implementado pelo compilador. Portanto, de onde quer que você chame printLocation, você obterá o mesmo resultado.
A única maneira de fazer isso funcionar é transformar printLocation em uma macro. (Sim eu conheço...)
fonte
A situação com inline, inline estático e inline externo é complicada, até porque gcc e C99 definem significados ligeiramente diferentes para seu comportamento (e presumivelmente C ++, também). Você pode encontrar algumas informações úteis e detalhadas sobre o que eles fazem em C aqui .
fonte
As macros são sua escolha aqui, em vez das funções embutidas. Uma ocasião rara em que as macros dominam as funções embutidas. Tente o seguinte: Escrevi este código "MACRO MAGIC" e deve funcionar! Testado em gcc / g ++ Ubuntu 10.04
Para vários arquivos, defina essas macros em um arquivo de cabeçalho separado, incluindo o mesmo em cada arquivo c / cc / cxx / cpp. Prefira funções inline ou identificadores const (conforme o caso) em vez de macros sempre que possível.
fonte
Em vez de responder "o que isso faz?", Estou respondendo "como faço para fazer o que quero?" Existem 5 tipos de inlining, todos disponíveis em GNU C89, C99 padrão e C ++:
sempre inline, a menos que o endereço seja obtido
Adicione
__attribute__((always_inline))
a qualquer declaração e use um dos casos abaixo para lidar com a possibilidade de seu endereço ser tomado.Você provavelmente nunca deve usar isso, a menos que precise de sua semântica (por exemplo, para afetar o assembly de uma determinada maneira ou para usar
alloca
). O compilador geralmente sabe melhor do que você se vale a pena.embutir e emitir um símbolo fraco (como C ++, também conhecido como "apenas faça funcionar")
Observe que isso deixa um monte de cópias do mesmo código por aí e o vinculador escolhe uma arbitrariamente.
inline, mas nunca emite nenhum símbolo (deixando referências externas)
emitir sempre (para um TU, para resolver o anterior)
A versão sugerida emite um símbolo fraco em C ++, mas um símbolo forte em qualquer dialeto de C:
Ou você pode fazer isso sem a dica, que emite um símbolo forte em ambos os idiomas:
Geralmente, você sabe qual é o idioma do seu TU ao fornecer as definições e provavelmente não precisa de muitos inlining.
inline e emitir em cada TU
Para todos eles, exceto
static
um, você pode adicionar umavoid foo(void)
declaração acima. Isso ajuda na "prática recomendada" de escrever cabeçalhos limpos e, em seguida,#include
inserir um arquivo separado com as definições embutidas. Então, se estiver usando sequências de estilo C,#define
alguma macro de maneira diferente em uma TU dedicada para fornecer as definições fora de linha.Não se esqueça
extern "C"
se o cabeçalho pode ser usado tanto em C quanto em C ++!fonte
nm
equivalente.