【发布时间】:2020-05-10 23:39:55
【问题描述】:
COM VARIANT 类型是使用tagVARIANT 结构定义的,如下所示:
typedef struct tagVARIANT {
union {
struct {
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union {
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
VARIANT_BOOL __OBSOLETE__VARIANT_BOOL;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown *punkVal;
IDispatch *pdispVal;
SAFEARRAY *parray;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
LONGLONG *pllVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
VARIANT_BOOL *__OBSOLETE__VARIANT_PBOOL;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
IUnknown **ppunkVal;
IDispatch **ppdispVal;
SAFEARRAY **pparray;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
ULONGLONG ullVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
ULONGLONG *pullVal;
INT *pintVal;
UINT *puintVal;
struct {
PVOID pvRecord;
IRecordInfo *pRecInfo;
} __VARIANT_NAME_4;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
} VARIANT;
通常,当调用者想要使用 Variant 中的数据时,它会使用 VARTYPE vt 标志来查看存储的数据类型,以及最终应该如何解释这些 1 和 0。
当DECIMAL 存储在 Variant 中时会发生什么;定义位于包含vt 的struct 之外,那么调用者如何确定是否存在有效的类型标志或只有十进制的某些字节? Decimal 需要 12* 14 个字节来存储,而 Variant 可以保存 16 个字节,因此可能会利用此信息,但不是存储在联合的较小成员的备用 2 个字节中的内容未定义的行为?
【问题讨论】:
-
@user253751 哦,我明白了,我误解了它是什么,但
DECIMAL是一个 12 字节无符号整数 + 2 字节符号/比例 + 2 字节保留,所以完整的 16 字节是确实定义了。但是,保留的 2 个字节中有什么内容? -
保留的 2 个字节恰好在 VARIANT 中与
vt重叠... -
@user253751 好的...那么这是否回答了呼叫者是否可以判断这是小数的问题?当然,这 2 个字节占据了调用者查看存储类型的位置,但它并没有说这些字节必须是或特别意味着什么,正如你所说,这只是一个巧合,对吧?如果存储 DECIMAL 的 VARIANT 想要使用这些字节作为 vt 标志,为什么不使用
struct{vt ; decVal}定义 VARIANT 和更短的十进制 2 个字节,或者使用typedef struct tagDEC {VARTYPE wReserved; ...的 DECIMAL 来明确说明这 2 个字节的含义? -
我不知道。但这就是它设法仍然有效的方式。
标签: c++ com decimal unions variant