(Не 1) по какой-то причине принимает значение -2

#vba #operators #bitwise-operators #bitwise-not

#vba #операторы #побитовые операторы #побитовый -не

Вопрос:

Почему (Не 1) вычисляется как -2? Я бы ожидал, что он будет вычислен как 0.

введите описание изображения здесь

Комментарии:

1. Два дополняют друг друга? В (8-разрядном) двоичном коде 1 равен 00000001 , а -2 — 11111110 , вы делаете побитовое нет.

2. Итак, как мне перестать выполнять побитовое нет? InStr возвращает позицию в строке, и мне нужно предпринять действия, если строка не найдена, т.Е. Если не InStr….

3. Ну, какое значение вы получите, если оно не найдено? Проверьте это.

4. InStr возвращает некоторый индекс, больший 0, если он найден, и применение Not приводит к значению -2. Таким образом, поскольку значение равно -2, а не 0, мой оператор if не работает

5. И что он возвращает, если не найден?! Может быть, проверить learn.microsoft.com/en-us/office/vba/language/reference /…

Ответ №1:

1 не является целочисленным представлением True , -1 является.

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

Логические операторы ( Not , And , Or , XOr ) ведут себя как «логические операторы», когда их операнды являются логическими значениями. Когда это не так, они ведут себя как «побитовые операторы», но правда в том, что они всегда побитовые.

Целочисленное значение 1 преобразуется в логическое значение True только потому, что True определено как Not False , что означает, что любое ненулевое значение является логическим True . Но вы получаете правильное / ожидаемое логическое поведение только при использовании -1 for True .

Integer Представлен 16 битами, так 1 это:

 0000 0000 0000 0001
  

Это делает Not 1 это:

 1111 1111 1111 1110
  

Знаковый бит включен, поэтому значение отрицательное — обрежьте незначимые цифры, и вы получите:

 10
  

Которое является двоичным представлением для 2 . Следовательно, Not 1 является -2 .

И наоборот, -1 было бы:

 1111 1111 1111 1111
  

И Not -1 таким образом:

 0000 0000 0000 0000
  

Ответ №2:

В VBA / VBScript нет реальных логических операторов (AND, ИЛИ, NOT). Логические операторы, которые вы видите, на самом деле являются побитовыми операторами, и это все, что вы получаете. VBA играет в некоторые игры со значениями True и False , так что большую часть времени это работает, но иногда вы обнаружите «ошибку».

В этом случае вместо If Not InStr() Then вы должны написать If InStr() <= 0 Then .
Вместо If InStr() Then вы должны написать If InStr() > 0 Then

Другими словами: InStr() возвращает число. Не пытайтесь рассматривать это как логическое значение.

Комментарии:

1. Хороший, краткий ответ — последнее предложение является ключевым.

Ответ №3:

Поскольку в других ответах уже объяснялось, почему, я хочу сосредоточиться на методах кодирования.

Как вы выяснили, Not x это не обязательно то, что вы хотите. На практике вы хотите больше похожего Not CBool(x) . Однако CBool() может выдавать ошибки — например, CBool(Null) выдает ошибку 91 (недопустимое использование null).

Можно утверждать, что вы можете избежать этого, строго введя свои переменные, но даже отсутствие a Variant не гарантирует, что в выражении a Boolean останется a Boolean . Пример:

 ?typename(true and 0)
Integer
  

На практике слишком легко случайно разрешить VBA выполнять за вас неявные преобразования voodoo, поэтому по этим причинам изменение привычек кодирования может вам больше подойти.

Для проверки истинных значений вам нужны выражения типа:

If x Then

И для ложных значений вам нужны выражения типа:

If x = False Then

Это работает независимо от типа x , является ли это выражением или нет, и, следовательно, считается, что оно намного более последовательное / предсказуемое в своем поведении по сравнению с If x = True Then or If Not x Then . Приняв эту привычку к кодированию, вы можете помочь избежать создания незначительных ошибок, возникающих из-за случайного отклонения от Boolean типов и получения побитовой операции, а не логической операции.

Для назначений использование Boolean переменной будет работать, гарантируя, что она последовательно преобразуется в True или False , а не в какие-то случайные числа.