#vba #operators #bitwise-operators #bitwise-not
#vba #операторы #побитовые операторы #побитовый -не
Вопрос:
Комментарии:
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
, а не в какие-то случайные числа.