Question Pourquoi GCC définit-il l'opérateur unaire '&&' au lieu de simplement utiliser '&'?


Comme discuté dans cette question, GCC définit un opérateur unaire non standard && prendre l'adresse d'une étiquette.

Pourquoi définit-il un nouvel opérateur, au lieu d'utiliser la sémantique existante du & opérateur et / ou la sémantique des fonctions (où foo et &foo les deux donnent l'adresse de la fonction foo())?


23
2018-04-28 07:56


origine


Réponses:


Les noms d'étiquette n'interfèrent pas avec d'autres identificateurs, car ils ne sont utilisés que dans les gotos. Une variable et un label peuvent avoir le même nom, et dans les standards C et C ++, il est toujours clair du contexte. Donc c'est parfaitement valable:

name:
  int name;
  name = 4; // refers to the variable
  goto name; // refers to the label

La distinction entre & et & & est donc nécessaire pour que le compilateur sache quel type de nom attendre:

  &name; // refers to the variable
  &&name; // refers to the label

37
2018-04-28 07:59



GCC a ajouté ceci extension à utiliser pour initialiser un tableau statique qui servira de table de saut:

static void *array[] = { &&foo, &&bar, &&hack };  

foo, bar et hack sont des étiquettes. Ensuite, une étiquette peut être sélectionnée avec l'indexation, comme ceci:

goto *array[i];   

Standard dit que

C11: 6.2.1 Étendue des identificateurs (p1):

Un identifiant peut désigner un objet; une fonction; une étiquette ou un membre d'une structure, d'une union ou d'une énumération; un nom de typedef; une nom de l'étiquette; un nom de macro; ou un paramètre macro.

En outre, il est dit dans la section 6.2.3:

Si plus d'une déclaration d'un identifiant particulier est visible à un point quelconque d'une unité de traduction, le contexte syntaxique ne fait pas de distinction entre les utilisations faisant référence à différentes entités. Ainsi, il y a séparer les espaces de noms pour différentes catégories d'identificateurs, comme suit:

- noms d'étiquette (désambiguïsées par la syntaxe de la déclaration et de l’utilisation de l’étiquette);

- la Mots clés des structures, des unions et des énumérations (sans ambiguïté en suivant une quelconque32) des mots-clés struct, union, ou enum);

- la membres des structures ou des syndicats; chaque structure ou union a un espace de nom distinct pour ses membres (désambiguïsés par le type de l'expression utilisée pour accéder au membre via le . ou -> opérateur);

- tous les autres identificateurs, appelés identificateurs ordinaires (déclarés dans des déclarateurs ordinaires ou en tant que constantes d'énumération).

Cela signifie que un objet et une étiquette peuvent être désignés par le même identifiant. À ce stade, laisser le compilateur savoir que l'adresse de foo est l'adresse d'une étiquette, pas l'adresse d'un objet foo (s'il existe), GCC défini && opérateur pour l'adresse de l'étiquette.


9
2018-04-28 11:02