web-dev-qa-db-fra.com

Que signifie le double soulignement (__const) en C?

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

J'ai trouvé la définition de fonction ci-dessus dans /usr/include/netinet/ether.h sur une boîte Linux.

Quelqu'un peut-il expliquer ce que signifient les doubles soulignés devant const (mot-clé), addr (identifiant) et enfin __THROW.

47
Deepak

En C, les symboles commençant par un trait de soulignement suivi d'une lettre majuscule ou d'un autre trait de soulignement sont réservés à l'implémentation. En tant qu'utilisateur de C, vous ne devez pas créer de symboles commençant par les séquences réservées. En C++, la restriction est plus stricte; vous, l'utilisateur ne peut pas créer un symbole contenant un double soulignement.

Donné:

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;

La notation __const Est là pour permettre la possibilité (quelque peu improbable) qu'un compilateur que ce code soit utilisé avec des notations de prototype prend en charge mais ne comprenne pas correctement le mot clé standard C89 const. Les macros autoconf peuvent toujours vérifier si le compilateur a un support fonctionnel pour const; ce code pourrait être utilisé avec un compilateur cassé qui n'a pas ce support.

L'utilisation de __hostname Et __addr Est une mesure de protection pour vous, l'utilisateur de l'en-tête. Si vous compilez avec GCC et l'option -Wshadow, Le compilateur vous avertira lorsque des variables locales masquent une variable globale. Si la fonction n'utilisait que hostname au lieu de __hostname, Et si vous aviez une fonction appelée hostname(), il y aurait un effet miroir. En utilisant des noms réservés à l'implémentation, il n'y a pas de conflit avec votre code légitime.

L'utilisation de __THROW Signifie que le code peut, dans certaines circonstances, être déclaré avec une sorte de "spécification de lancement". Ce n'est pas la norme C; c'est plus comme C++. Mais le code peut être utilisé avec un compilateur C tant que l'un des en-têtes (ou le compilateur lui-même) définit __THROW À vide, ou à une extension spécifique au compilateur de la syntaxe C standard.


La section 7.1.3 de la norme C (ISO 9899: 1999) dit:

7.1.3 Identifiants réservés

Chaque en-tête déclare ou définit tous les identifiants répertoriés dans son sous-paragraphe associé, et déclare ou définit facultativement les identifiants répertoriés dans le sous-paragraphe et les identifiants des directions de bibliothèque qui lui sont associés qui sont toujours réservés soit pour une utilisation soit pour une utilisation comme identificateurs de portée de fichier.

- Tous les identifiants qui commencent par un trait de soulignement et soit une lettre majuscule ou un autre trait de soulignement sont toujours réservés à toute utilisation.

- Tous les identificateurs qui commencent par un trait de soulignement sont toujours réservés pour être utilisés comme identificateurs avec une portée de fichier dans les espaces de nom ordinaires et de balises.

- Chaque nom de macro dans l'un des sous-paragraphes suivants (y compris les futures directions de bibliothèque) est réservé pour une utilisation telle que spécifiée si l'un de ses en-têtes associés est inclus; sauf indication contraire explicite (voir 7.1.4).

- Tous les identifiants avec liaison externe dans l'un des sous-paragraphes suivants (y compris les futures instructions de bibliothèque) sont toujours réservés pour être utilisés comme identifiants avec liaison externe.154)

- Chaque identifiant avec portée de fichier répertorié dans l'un des sous-paragraphes suivants (y compris les futures instructions de bibliothèque) est réservé pour être utilisé comme nom de macro et comme identifiant avec portée de fichier dans le même espace de nom si l'un de ses en-têtes associés est inclus.

Aucun autre identifiant n'est réservé. Si le programme déclare ou définit un identifiant dans un contexte dans lequel il est réservé (autre que celui autorisé par 7.1.4), ou définit un identifiant réservé comme nom de macro, le comportement n'est pas défini.

Si le programme supprime (avec #undef) Toute définition de macro d'un identifiant dans le premier groupe répertorié ci-dessus, le comportement n'est pas défini.

Note de bas de page 154) La liste des identificateurs réservés avec liaison externe comprend errno, math_errhandling, setjmp et va_end.


Voir aussi Quelles sont les règles d'utilisation d'un trait de soulignement dans un identifiant C++ ; un grand nombre des mêmes règles s'appliquent à la fois à C et C++, bien que la règle de double soulignement incorporée soit uniquement en C++, comme mentionné en haut de cette réponse.

69
Jonathan Leffler

Les noms avec des soulignements doubles en tête sont réservés à l'utilisation par l'implémentation. Cela ne signifie pas nécessairement qu'ils sont internes en soi, bien qu'ils le soient souvent.

L'idée est que vous n'êtes pas autorisé à utiliser des noms commençant par __, donc l'implémentation est libre de les utiliser dans des endroits comme les extensions de macro ou dans les noms d'extensions de syntaxe (par exemple __gcnew ne fait pas partie de C++, mais Microsoft peut l'ajouter à C++/CLI en sachant qu'aucun code existant ne devrait avoir quelque chose comme int __gcnew; qui arrêterait de compiler).

Pour savoir ce que ces extensions spécifiques signifient, par exemple __const vous devrez consulter la documentation de votre compilateur/plateforme spécifique. Dans ce cas particulier, vous devriez probablement considérer le prototype dans la documentation (par exemple http://www.kernel.org/doc/man-pages/online/pages/man3/ether_aton.3.html ) pour être l'interface de la fonction et ignorer le __const et __THROW décorations qui apparaissent dans l'en-tête réel.

19
Logan Capaldo

Par convention dans certaines bibliothèques, cela indique qu'un symbole particulier est à usage interne et n'est pas destiné à faire partie de l'API publique de la bibliothèque.

3
Rob H

Le trait de soulignement dans __const signifie que ce mot clé est une extension du compilateur et que son utilisation n'est pas portable (le mot clé const a été ajouté à C dans une révision ultérieure, 89 je pense). Le __THROW est aussi une sorte d'extension, je suppose qu'il est défini sur un __attribute __ (quelque chose) si gcc est utilisé, mais je ne suis pas sûr à ce sujet et trop paresseux pour vérifier. Le __addr peut signifier tout ce que le programmeur voulait qu'il signifie, c'est juste un nom.

2
Caotic