3
votes

(Not 1) donne -2 pour une raison quelconque

Pourquoi est-ce que (Not 1) vaut -2? Je m'attendrais à ce qu'il soit évalué à 0.

 entrez la description de l'image ici


5 commentaires

Complément à deux? En binaire (8 bits), 1 est 00000001 et -2 est 11111110 , vous faites un peu pas.


Alors, comment puis-je arrêter de faire un peu pas? InStr renvoie une position dans une chaîne et je dois prendre des mesures si une chaîne n'est pas trouvée, c'est-à-dire If Not InStr ....


Eh bien, quelle valeur obtenez-vous si elle n'est pas trouvée? Vérifiez cela.


InStr renvoie un index supérieur à 0 s'il est trouvé, et l'application de Not rend la valeur -2. Ainsi, comme la valeur est -2 et non 0, mon instruction if ne fonctionne pas


Et que renvoie-t-il s'il n'est pas trouvé?! Peut-être vérifier docs.microsoft.com/en-us/office/vba/language/reference/...


3 Réponses :


3
votes

VBA / VBScript n'a pas de vrais opérateurs logiques (AND, OR, NOT). Les opérateurs logiques que vous voyez sont en fait des opérateurs au niveau du bit, et c'est tout ce que vous obtenez. VBA joue à certains jeux avec les valeurs True et False , donc cela fonctionne la plupart du temps, mais parfois vous trouverez un "gotcha".

Dans ce cas, au lieu de If Not InStr () Then , vous devez écrire If InStr () <= 0 Then .
Au lieu de If InStr () Then , vous devez écrire If InStr ()> 0 Then

En d'autres termes: InStr () renvoie un nombre . N'essayez pas de le traiter comme un booléen.


1 commentaires

Bonne réponse concise - la dernière phrase est la clé.



5
votes

1 n'est pas la représentation entière de True , -1 l'est.

0000 0000 0000 0000

Opérateurs booléens ( Not , And , Or , XOr ) se comportent comme des "opérateurs logiques" lorsque leurs opérandes sont des valeurs booléennes. Lorsqu'ils ne le sont pas, ils se comportent comme des "opérateurs au niveau du bit", mais la vérité est qu'ils sont toujours au niveau du bit.

La valeur entière 1 est convertie à la valeur booléenne True uniquement parce que True est défini comme Not False , ce qui signifie que toute valeur non nulle est une valeur booléenne True . Mais vous n'obtenez le comportement logique correct / attendu que lorsque vous utilisez -1 pour Vrai.

Un Integer est représenté par 16 bits, donc 1 est ceci:

1111 1111 1111 1111

Cela fait Not 1 ceci:

10

Le bit de signe est activé, donc la valeur est négative - coupez les chiffres insignifiants et vous obtenez:

1111 1111 1111 1110

Quelle est la représentation binaire pour 2 . Par conséquent, Not 1 est -2 .

Inversement, -1 serait:

0000 0000 0000 0001

Et Not -1 est donc:

Debug.Print CInt(True) 'prints -1
Debug.Print CInt(False) 'prints 0


0 commentaires

2
votes

Comme les autres réponses l'ont déjà expliqué sur le pourquoi , je souhaite me concentrer sur les pratiques de codage.

Comme vous l'avez découvert, Not x n'est pas nécessairement ce que tu veux. En pratique, vous voulez plus comme Pas CBool ​​(x) . Cependant, CBool ​​() peut générer des erreurs - par exemple, CBool ​​(Null) renvoie l'erreur 91 (utilisation invalide de null).

On peut prétendre que vous pouvez éviter cela en tapant fortement vos variables, mais même en n'utilisant pas de Variant , cela ne garantit pas que dans une expression un code Boolean > restera un Booléen . Exemple:

?typename(true and 0)
Integer

En pratique, il est trop facile d'autoriser accidentellement VBA à effectuer les conversions implicites vaudou pour vous, donc pour ces raisons, modifier les habitudes de codage pourrait vous convenir mieux.

Pour tester les valeurs de vérité, vous voulez des expressions telles que:

If x Then

Et pour les valeurs fausses, vous voulez des expressions comme:

If x = False Then

Cela fonctionne quel que soit le type du x , qu'il s'agisse d'une expression ou non et on dit donc qu'il est beaucoup plus cohérent / prévisible dans son comportement par rapport à If x = True Then ou If Not x Then . En adoptant cette habitude de code, vous pouvez éviter de créer des bogues subtils résultant d'une conversion accidentelle loin des types Boolean et d'obtenir une opération au niveau du bit plutôt qu'une opération logique.

Pour les affectations, en utilisant un La variable Boolean fonctionnera pour s'assurer qu'elle est systématiquement forcée en True ou False et non pas dans certains nombres aléatoires.


0 commentaires