【发布时间】:2019-11-18 02:55:29
【问题描述】:
一些假设:(如果错了,请纠正我)
忽略 16 位内容,VBA 可以在 32 位或 64 位 Office 主机上运行。 64 位 Office 只能在 64 位操作系统上运行,而您可以在 32 或 64 位版本的 Windows/macOS/其他操作系统上运行 32 位 Office。
从 VBA7 开始,我们有 LongPtr 类型,它在 32 位 Office (#Win64 = False) 上变为 Long,在 64 位 Office (#Win64 = True) 上变为 LongLong,不管操作系统位数
我的问题:在处理指针(内存中的地址)的 API 中,操作系统位数是否重要,或者仅仅是运行我们关心的代码的应用程序(32 /64 位 Office 主机/VBA)?
目前的理解:
一方面,我明白为什么它可能无关紧要:
- 在 32 位 Excel 中运行的 VBA 将具有 32 位地址空间(与操作系统无关)
- 因此,任何指向其自身内存的指针都应该是 32 位的(即
Longs -LongPtr给了我们这个) - 类似的 64 位 VBA(必须在 64 位操作系统中,但实际上可以在任何地方)有一个 64 位地址空间(每个指针本身都是 64 位长,并且指的是一个 64 位宽的内存块)
- 因此,任何指向其自身内存的指针都应该是 64 位的(即
LongLongs -LongPtr给了我们这个) - 所以
LongPtr准确地表示了一个指向我的代码自己的内存的指针,而不管操作系统位数如何
但是我可以想象操作系统位数可能很重要的时候
- 在 64 位操作系统上运行 32 位 VBA,但想要引用不同 64 位应用程序的内存区域,
LongPtr类型将评估为Long,并且太短而无法表示最大值该操作系统中可用的指针大小。 - 类似地,访问 32 位应用程序的内存的 64 位 VBA 会发现其指针类型太大而无法容纳地址
- 现在备受信任的
LongPtr类型实际上是错误的长度来表示指向VBA 自身地址空间之外的内存地址的指针!
问题现在可能取决于操作系统位数,而不是 Office/VBA 位数。如果我们在 32 位操作系统上运行 VBA7,那么LongPtr 将是您想要投入的任何内存块的正确长度;在 99.9% 的情况下它是合适的指针数据类型,因为操作系统所做的一切都是 32 位(忽略 16 位)。
但是,在尝试使用 LongPtr 保存 32 位地址时,在 64 位操作系统上运行相同的 32 位 VBA7 代码会遇到困难。我觉得在 64 位操作系统上混合 32 位和 64 位应用程序是很常见的,所以这可能是一个真正的问题。
在 32 位和 64 位操作系统上运行的 32 位 VBA6 和更早的应用程序可能会面临类似的问题,除非 LongPtr 的帮助
现在我明白这是一个非常人为的情况,谁会想要访问另一个应用程序的内存,对吧?事实上,它太做作了,我不确定我是否能想出一个重要且值得担心的情况。一个应用程序能否获得另一个具有不同位数的应用程序的内存地址?也许有一些读写保护可以防止这种情况发生。
也许访问另一个应用程序的窗口句柄就是这样一种情况;那是公共内存,也许窗口句柄的位数反映了应用程序或操作系统的位数,在这种情况下,我的 32 位 VBA 想要持有对 64 位 Hwnd 的引用是可行的,我不确定...
PS 我知道除了指针长度之外,操作系统位数可能很重要。我知道一个; SetWindowLong 函数在 64 位和 32 位 Windows 上需要不同的声明——尽管 IIUC 现在已经用 SetWindowLongPtr 函数解决了,这两者都是相同的。但是任何其他类似的怪癖都会很有用,我在这里只关注指针长度,因为我有一个需要特定信息的问题。
PPS 想一想,你甚至可以在编译时获得操作系统位数吗?我想你可以从MAC_OFFICE_VERSION 推断出来,而ofc Win64 = True 表示64 位Office 和事实上的64 位操作系统。但我不确定是否有办法判断 32 位 VBA 是否在 64 位 Windows 上运行...
【问题讨论】:
-
当然可以。正如您所指出的,操作系统的位数会影响
LongPtr的字节数。这可能只是真正影响那些在 64 位系统上拥有 32 位办公室的人,并且 API 使用 8 个字节作为参数。我想,只要 API 规范知道LongPtr可以有不同的值,就使用正确的类型? -
32 位 VBA 要保留对 64 位 Hwnd 的引用 至少对于 Hwnd 来说这并不重要,因为即使是 64 位操作系统也可以使用 32 -Bit Handles:docs.microsoft.com/en-us/windows/win32/winprog64/… 该链接还包含一些有关您将如何处理此类事情的信息。
-
还有:根据stackoverflow.com/a/1822738/10223558 Hwnd 是一个索引而不是一个指针,所以操作系统的位数不应该真的有影响。
-
@L8n 64 位返回值如何适合 32 位?
-
@RyanWildry 是的,如果 API 需要 8 字节(64 位)的数据,那么当
LongPtr的数据不长时,32 位 Office 上的用户可能会被绊倒。想法。但首先,这并不是我真正关心的问题。假设 API 函数为QueryPerformanceFrequency。我会争辩说,在您的示例中,用户使用了错误的数据类型 - API 要求提供LARGE_INTEGER,而不是指针,因此虽然LongPtr恰好在 64 位中为它们工作,但在 32 位中没有有点办公室,无论哪种方式都是错误的选择。
标签: vba pointers operating-system 32bit-64bit conditional-compilation