Question Pourquoi int _ $ [:> = <% - !. 0,}; compiler?


Aujourd'hui, j'ai trouvé une syntaxe étrange comme

 int _$[:>=<%-!.0,};

dans un ancien code, mais en fait le code n'est pas commenté. Il semble n'y avoir aucun rapport d'erreurs de compilation pour cette ligne. Je l'ai testé séparément et il peut aussi être compilé:

int main(){
    int _$[:>=<%-!.0,};
    return 0;
}

Pourquoi peut-il compiler?


42
2017-08-14 03:00


origine


Réponses:


Avec Digraph (voir ci-dessous), la ligne est convertie en:

int _$[]={-!.0,};

À droite .0 est le double littéral, ! est l'opérateur de négation logique, - est l'opérateur de négation arithmétique, et , est la virgule de fin. Ensemble {-!.0,} est un initialiseur de tableau.

Le côté gauche int _$[] définit un int tableau. Cependant, il y a un dernier problème, _$ n'est pas un identifiant valide dans la norme C. Certains compilateurs (par exemple, gcc) le prend en charge en tant qu’extension.


C11 §6.4.6 Ponctuators

Dans tous les aspects de la langue, les six jetons

<: :> <% %> %: %:%:

se comporter, respectivement, comme les six jetons

[  ]  {  }  #  ##

47
2017-08-14 03:04



Bien,

  • souligner _ est un identifiant autorisé,
  • signe dollar $ est autorisé dans certaines implémentations aussi,
  • support gauche [ indique que le type doit être un tableau,
  • :> est le digraphe pour ],
  • équivaut à = est l'affectation,
  • <% est le digraphe pour {,
  • -!.0 est juste -1 (.0 est un double littéral 0.0, ! implicitement jette à (int) 0 et l'inverse logiquement, et - est négatif),
  • vous pouvez avoir des virgules à la fin dans les initialiseurs de tableau {1, (2, 3,)},
  • et ; termine la déclaration.,

Donc, vous obtenez

int _$[] = {-1,};

38
2017-08-14 03:24



Si on remplace les digraphes :> et <% présent dans votre ligne de code, nous nous retrouvons avec

int _$[]={-!.0,};

ce qui équivaut à

int _$[] = { -1, };

C'est une déclaration de tableau _$ de type int [1] avec un initialiseur.

Notez que cela ne garantit pas exactement la compilation car le langage C standard ne prend pas immédiatement en charge $ caractère en identificateurs. Cela permet aux implémentations d'étendre l'ensemble des charaters pris en charge. Apparemment, le compilateur que vous avez utilisé a supporté $ dans les identifiants.


11
2017-08-14 03:18



Cela fonctionne en raison de digraphes en C. La ligne en question décode comme ceci:

int _$ [ :> = <% - ! .0  , } ;
int _$ [ ]  = {  - ! 0.0 , } ;

En outre:

  • .0 est un double littéral.
  • ! est l'opérateur de négation booléen, donc !.0 les rendements (int) 1.
  • - est l'opérateur de négation unaire, qui cède (int) -1.
  • Une virgule de fin est légale après un élément de tableau.

11
2017-08-14 03:16