C ++ avec extern “C” dans la résolution de préfixe d’espace de nommage et la dépendance au niveau d’optimisation

J’ai un fichier “test.cxx” avec

namespace net { extern "C" { #include  } } int main() { htons(1024); } 

Lors de la compilation avec -O1 ou plus, tout va bien.

Lors de la compilation avec -O0 :

 error: 'htons' was not declared in this scope suggested alternative: 'net::htons' 

Ensuite, je change htons en net :: htons .

Lors de la compilation avec -O0 tout va bien.

Lors de la compilation avec -O1 ou plus:

 error: expected unqualified-id before '(' token 

Reproduit cela sur gcc-4.9.2 et clang-3.7.0. Quelqu’un peut-il expliquer pourquoi cela se produit?

Cela se produit car à -O0 , l’appel est compilé dans la fonction htons et votre déclaration pour cette fonction est à l’intérieur de l’ namespace net . Dans la version optimisée, -O2 par exemple, l’appel est remplacé par une macro.

Vous pouvez le vérifier en pré-compilant votre programme en utilisant gcc -O0 -E v / s gcc -O2 -E

Quand htons est utilisé
A -O2 , htons est traduit en

 int main() { (__extension__ ( { register unsigned short int __v, __x = (unsigned short int) (1024); if (__builtin_constant_p (__x)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; } )); } 

Faire le code ne pas jeter l'erreur de résolution.

erreur: 'htons' n'a pas été déclaré dans cette scope

Quand net :: htons est utilisé

Lorsque vous remplacez ntohs par net::ntohs , ntohs define est utilisé / exposé pour l'optimisation et votre code pré-traité ressemble à:

 int main() { net::(__extension__ ({... /* removed for Brevity */ ...})); } 

Et donc l'erreur

erreur: id non qualifié attendu avant '(' jeton

Pourquoi ça arrive
htons peut être implémenté comme une fonction ou une macro. S'il est défini en tant que macro, htons fonctionnerait bien. Mais si elle est définie comme une fonction net::htons fonctionnerait bien.

Il apparaît à -O1 ou supérieur, les fichiers d'en-tête exposent les versions macro au lieu de la fonction.

Solutions possibles

 using namespace net; // Not recommended 
 #ifndef htons // Recommended using net::htnos; #endif 
 extern "C" { // Add all declarations in global space #include  }