Логические операторы VBS инициализируют пустые переменные?

Рассмотрим следующий бит VBS:

dim msg, myVar, myVar2

msg = "myVar = " & myVar
msg = msg & vbcrlf & "myVar = empty: " & isempty(myVar)
msg = msg & vbcrlf & "TypeName(myVar) = " & TypeName(myVar)

msgbox msg, , "BEFORE"

if not myVar then myVar2 = true

msg = "myVar = " & myVar
msg = msg & vbcrlf & "myVar = empty: " & isempty(myVar)
msg = msg & vbcrlf & "TypeName(myVar) = " & TypeName(myVar)

msgbox msg, , "AFTER"

Я ожидаю, что результат от "ПЕРЕД" и "ПОСЛЕ" будет таким же... все, что мы делаем, делает сравнение с неинициализированным (пустым) вариантом справа?

Однако - кажется, что "если нет" фактически инициализирует его (длинный) ноль! Я кодировал в VBS (ASP) для осла лет, и это новое на меня!

Несколько замечаний:

  • Поведение одинаково как в .vbs, так и в эквивалентном ASP-коде (на моем рабочем столе Win 7 и на сервере 2008 R2).
  • Все логические операторы - и/или/не/xor производят этот эффект
  • Операторы сравнения не делают.

Кажется, это потенциальная ловушка для неосторожного... Может ли кто-нибудь объяснить это поведение?

Ответ 1

Я не мог найти ничего официального в этой проблеме. После некоторого теста я решил, что это ошибка или не документированный эффект. Такое поведение не применяется на других подобных платформах, таких как VBA и VB6.

Visual Basic для приложения:

Visual Basic для приложения

Visual Basic 6:

Visual Basic 6

VBScript:

VBScript

В качестве обходного пути выполняется передача выражений по значению.

If Not (exp) Then
'or
If Not CBool(exp) Then

Параметры ByRef и ByVal
Функция CBool ​​

Ответ 2

Если вы измените этот оператор в середине на

if not (myVar) then myVar2 = true   'with parenthesis around myVar

то вы не будете свидетелями такого же поведения. ПЕРЕД ИСПОЛЬЗОВАНИЕМ ПОСЛЕ ТОГО, ПОСЛЕ ИСПОЛЬЗОВАНИЯ.

Это потому, что, видимо, скобки вынуждают оператор Not выполнять только логический тест и пропускают побочный эффект Not.

В https://msdn.microsoft.com/en-us/subscriptions/9cy86sfb%28v=vs.84%29.aspx вы найдете следующее: Не

In addition, the Not operator inverts the bit values of any variable and
sets the corresponding bit in result according to the following table:
+-------------------+---------------+
| Bit in expression | Bit in result |
+-------------------+---------------+
| 0                 | 1             |
| 1                 | 0             |
+-------------------+---------------+

Например

Msgbox Not 2   ' is -3
Msgbox Not -3  ' is 2

Это имеет смысл, если вы считаете, что внутри значения хранятся как подписанные байты/слова.

000 -4
001 -3  --> 001 inverted is 110
010 -2
011 -1
100  0
101  1
110  2  --> 110 inverted is 001
111  3

Позвольте преобразовать Empty в Long с помощью

x = CLng(myVar)

Вы увидите, что значение x равно 0.

Если вы используете

if not myVar then myVar2 = true

тогда результат не myVar будет оценен (и полученное значение -1 будет впоследствии выбрано). Но расчет имеет место так или иначе, и для этого необходимо сначала преобразовать Empty в длинный.

Ответ 3

https://technet.microsoft.com/en-us/library/ee198865.aspx

Итак, если вы создадите переменную без ее инициализации, переменная примет одно из следующих значений по умолчанию: Если вы используете переменную как строку, начальное значение будет пустым. Если вы используете переменную как число, начальное значение будет равно 0.

Я бы подумал, что, поскольку вы выполняете логическую проверку, вы, по существу, используете myVar как число, и ваше утверждение читается так:

if not 0 then myVar2 = true
'same as: if not FALSE then myVar2 = true

И поэтому myVar инициализируется 0

Ответ 4

Это правила из VBA https://msdn.microsoft.com/en-us/library/ee177324.aspx?f=255&MSPPError=-2147217396

Дело в том, что переменные (хотя и не объекты) всегда имеют полезное значение (объекты имеют значение ничего).

5.5.1.2.2 Пусть-принуждение к и от булева

Если значение не сохраняется в качестве логического значения, False представляется 0, а значение True представлено ненулевыми значениями, обычно -1.

Семантика булевского let-coercion зависит от типа значения источника и объявленного типа назначения:

Source Value Type Destination Declared Type Semantics
Boolean     Boolean     The result is a copy of the source value.
Boolean     Any numeric type except Byte     If the source value is False, the result is 0. Otherwise, the result is -1.
Boolean     Byte     If the source value is False, the result is 0. Otherwise, the result is 255.
Any numeric type     Boolean     If the source value is 0, the result is False. Otherwise, the result is True

5.5.1.2.11 Пусть-принудительное из Empty

Семантика пустого Let-coercion зависит от типа объявленного адреса:

Source Value Type Destination Declared Type Semantics
Empty Any numeric type The result is 0.
Empty Boolean The result is False.
Empty Date The result is 12/30/1899 00:00:00.
Empty String The result is a 0-length string.
Empty String * length The result is a string containing length spaces.
Empty Any class or Object Runtime error 424 (Object required) is raised.
Empty Any other type except Variant Runtime error 13 (Type mismatch) is raised.

Ваша переменная принудительно используется как строка, когда вы впервые открываете ее.

Затем он принуждается как ложный в строке выше.

5.6.9.5. Реляционные операторы Реляционные операторы - это простые операторы данных, которые выполняют сравнения между их операндами.

relational-operator = equality-operator / inequality-operator / less-than-operator / greaterthan-operator / less-than-equal-operator / greater-than-equal-operator

Статическая семантика:

Реляционные операторы статически разрешены как простые операторы данных.

Оператор отношения недействителен, если объявленный тип любого операнда является массивом или UDT.

Реляционный оператор имеет следующий объявленный тип, основанный на объявленном типе его операндов:

Left Operand Declared Type Right Operand Declared Type Operator Declared Type
Any type except an array, UDT or Variant Any type except an array, UDT or Variant Boolean Any type except an array or UDT Variant 
 Variant Any type except an array or UDT Variant

Семантика времени выполнения:

Реляционные операторы сначала оцениваются как простые операторы данных.

Если тип значения любого операнда является массивом или UDT, возникает ошибка времени выполнения 13 (несоответствие типов).

Прежде чем оценивать реляционный оператор, его непустые операнды претерпевают Let-coercion к типу эффективного значения операторов.

Тип эффективного значения определяется следующим образом на основе типов значений операндов:

5.6.9.5.1 = Оператор

Оператор = выполняет сравнение значений по своим операндам.     равенство-оператор = выражение "=" выражение

Семантика времени выполнения:

Если операнды считаются равными, возвращается True. В противном случае возвращается False.