Некоторая дополнительная информация о VARIANT: они несколько странные в том смысле, что они являются составными типами: это в основном объединение нескольких типов, причем поля для каждого типа (bstrVal, lVal, punkVal и т. Д.) Занимают одно и то же пространство впамять и поле vt, указывающее, какое поле является действительным.
Вам следует пытаться получить доступ только к полю, которое соответствует значению vt.Таким образом, если vt равен VT_BSTR, тогда допустим только bstrVal;punkVal запрещен.Если vt равен VT_I4, то следует использовать только поле lVal.
VT_EMPTY означает, что «этот вариант не был установлен на какое-либо значение, поэтому ничего не представляет»;когда vt равен VT_EMPTY, все поля являются недопустимыми - они могут быть тем мусором, который только что находился в стеке ранее - это то, что вы видите здесь.
В Win64 целые числа по-прежнему 32-битные,но указатели 64-битные.Вариант с типом VT_I4 со значением 0 будет иметь 32 бита, представляющих целое число, установленное в 0, но остальная часть памяти в варианте может быть любой оставшейся фигней.Если вы попытаетесь обработать эту память как 64-битный указатель - путем доступа к punkVal - тогда вы получите указатель, созданный из этих 32 0 битов, но также из смежных 32 битов, которые никогда не были должным образом инициализированы - вероятно, поэтомувы видите различия между этими двумя случаями здесь.
В Win32 вам повезло: указатель имеет тот же размер, что и int, так что если вы обращаетесь к VT_I4, равному 0, и читаете punkVal (что вам не следует't!), в этом случае вы получите нулевой указатель.