60 votes

Que signifie " !!" en C ?

J'ai rencontré l'extrait suivant :

pt->aa[!!(ts->flags & MASK)] = -val;
  1. Qu'est-ce que !! (double point d'exclamation/ points d'exclamation/ deux opérateurs NOT) signifie-t-il en c ?
  2. Non. (!!NULL) == NULL ?

3 votes

1 votes

Exemple : Dans mon code " De décimal à binaire : Indépendant de la taille : Première méthode " J'ai utilisé !! pour convertir un int en 0 o 1 bit

3 votes

Veuillez également noter que ce code est mauvais. Problème 1 : utilisation d'un bool comme index de tableau. Problème 2 : la syntaxe bizarre ! !, qui ne fait qu'embrouiller le lecteur (comme on peut le voir dans cette question). Problème 3 : calcul de l'indice du tableau avec une expression complexe inutile, qui aurait dû être déplacée sur une ligne distincte. Toutes ces choses pointent vers la même chose : je soupçonne que nous avons un programmeur qui pense être terriblement intelligent, mais qui en réalité a beaucoup à apprendre sur la conception correcte d'un programme et la maintenance du code.

92voto

Jan Points 8207

! est la négation. Donc !! est la négation de la négation. Ce qui est important, c'est le fait que le résultat sera un int .

  • !!x si x == 0 es !!0 c'est-à-dire !1 c'est-à-dire 0 .
  • !!x si x != 0 es !!(!0) c'est-à-dire !!1 c'est-à-dire !0 c'est-à-dire 1 .

!! est utilisé couramment si vous voulez convertir toute valeur non nulle en 1 tout en étant certain que le 0 reste un 0.

Et en effet, !!NULL == NULL puisque !!NULL == !!0 y !!0 == !1 et enfin !1 == 0 .

Par conséquent, dans le court morceau de code que vous avez cité, l'indice du tableau sera soit 0 si la valeur de l'expression entre parenthèses est NULL y 1 autrement.

2 votes

La valeur qui en résulte est soit 0 o 1 de type int .

9 votes

(!!NULL) == NULL est vrai si NULL es 0 . Si NULL est, disons, ((void*)0) vous risquez d'obtenir un avertissement de comparaison entre un pointeur et un nombre entier. L'intérêt d'utiliser !! consiste à convertir les résultats des expressions "truey" et "falsy" en nombres entiers.

0 votes

@MikeDeSimone, @pmg, merci, j'ai ajouté l'information sur la valeur de l'expression étant un int .

29voto

unwind Points 181987

Il est couramment (ab)utilisé pour convertir n'importe quelle valeur dans le format int s 0 ou 1 par application répétée de l'opérateur booléen not, ! .

Par exemple : !56 est 0, puisque 56 est "vrai" lorsqu'il est vu comme un booléen. Cela signifie que !!56 est égal à 1, puisque !0 est de 1.

1 votes

Vous dites "abusé", mais c'est un idiome courant. Que suggérez-vous comme alternative concise ?

0 votes

@PCLuddite J'ai bien dit " (ab)utilisé ", laissant entendre que l'accusation d'abus est un peu légère ". Je recommanderais probablement pt->aa[(ts->flags & MASK) != 0] car je pense que c'est beaucoup plus clair et explicite.

0 votes

C'est bizarre, mais ce n'est pas l'un des pires abus du C, et certainement pas l'un des pires abus du C++. Ce langage a été construit pour l'abus de code.

7voto

ouah Points 75311

!E est la même chose que E == 0 donc !!E est la même chose que (E == 0) == 0 . !! est utilisé pour normaliser les valeurs booléennes.

4voto

tristopia Points 5074

En C99, vous pouvez le remplacer par

#include <stdbool.h>

pt->aa[(bool)(ts->flags & MASK)] = -val;

Bien sûr, si votre code doit être portable en C89, vous feriez mieux de faire le truc ! ! ou

pt->aa[(ts->flags & MASK)!=0] = -val;

ou

pt->aa[(ts->flags & MASK)?1:0] = -val;

Le code généré sera certainement identique.

4voto

Hot Licks Points 25075

Il convertit un nombre en un booléen canonique.

Et notez que dans ce cas, il est essentiel de le faire, puisque le résultat est utilisé pour indexer un tableau.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X