POINTER_32 - 它是什么,为什么?

发布于 2024-09-13 20:13:28 字数 261 浏览 2 评论 0原文

我刚刚接到将旧版应用程序从 32 位更新到 64 位的任务。在审查任务的范围时,我在包含外部(例如平台)标头之前立即发现了以下定义:

#define POINTER_32

我找不到使用此定义的内容或它具有什么效果,但它看起来像是那种将要使用的东西与我的任务直接相关!

它是做什么用的?它有什么用?立即删除它是否安全(我认为从长远来看有必要删除它)?

这是使用 MS VC++ 2008,即将是 2010 年。

I have just been given the task of updating a legacy application from 32-bit to 64-bit. While reviewing the extent of the task, I discovered the following definition immediately before the inclusion of external (eg. platform) headers:

#define POINTER_32

I cannot find what uses this definition or what effect it has, but it looks like the kind of thing that will be directly relevant to my task!

What is it for? What uses it? Will it be safe to remove it immediately (I presume it will be necessary to remove it in the long run)?

This is using MS VC++ 2008, soon to be 2010.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

眼前雾蒙蒙 2024-09-20 20:13:28

这是一个通常在 Windows SDK 头文件 BaseTsd.h 中声明的宏。在 32 位模式下编译时,它的定义如您所示。在 64 位模式下编译时,它被定义为

 #define POINTER_32 __ptr32

MSVC 编译器扩展,用于在 64 位代码模型中声明 32 位指针。 32 位代码还有 64 位风格:

 #define POINTER_64 __ptr64

如果您编写 64 位程序并且需要与另一个进程中 32 位代码使用的结构进行互操作,则可以使用它。例如:

typedef struct _SCSI_PASS_THROUGH_DIRECT32 {
    USHORT Length;
    UCHAR ScsiStatus;
    UCHAR PathId;
    UCHAR TargetId;
    UCHAR Lun;
    UCHAR CdbLength;
    UCHAR SenseInfoLength;
    UCHAR DataIn;
    ULONG DataTransferLength;
    ULONG TimeOutValue;
    VOID * POINTER_32 DataBuffer;      // <== here
    ULONG SenseInfoOffset;
    UCHAR Cdb[16];
}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32;

This is a macro that's normally declared in a Windows SDK header, BaseTsd.h header file. When compiling in 32-bit mode, it is defined as you showed. When compiling in 64-bit mode it is defined as

 #define POINTER_32 __ptr32

which is an MSVC compiler extension to declare 32-bit pointers in a 64-bit code model. There's also a 64-bit flavor for 32-bit code:

 #define POINTER_64 __ptr64

You'd use it if you write a 64-bit program and need to interop with structures that are used by 32-bit code in another process. For example:

typedef struct _SCSI_PASS_THROUGH_DIRECT32 {
    USHORT Length;
    UCHAR ScsiStatus;
    UCHAR PathId;
    UCHAR TargetId;
    UCHAR Lun;
    UCHAR CdbLength;
    UCHAR SenseInfoLength;
    UCHAR DataIn;
    ULONG DataTransferLength;
    ULONG TimeOutValue;
    VOID * POINTER_32 DataBuffer;      // <== here
    ULONG SenseInfoOffset;
    UCHAR Cdb[16];
}SCSI_PASS_THROUGH_DIRECT32, *PSCSI_PASS_THROUGH_DIRECT32;
老街孤人 2024-09-20 20:13:28

用于绕过警告C4244。在 32 位和 64 位模型中提供 32 位指针

Used to get around the Warning C4244 . Provides a 32-bit pointer in both 32-bit and 64-bit models

旧人哭 2024-09-20 20:13:28

我的客人是,它最初是为 VLM 创建的 (超大内存) 在 Alpha AXP 中,因为 Windows NT for Alpha 是 第一个具有部分 64 位支持的 Windows。 操作系统仍然是32位 但它具有 VLM API,供应用程序在必要时分配大64位内存,因此必须有某种方法在同一程序中声明 32 位和 64 位指针

VLM 返回应用必须存储的 POINTER_64。默认情况下使用 POINTER_32/__ptr32,而 POINTER_64/__ptr64 将在 64 位处理代码中

使用甚至仍然可以在 Windows 文档和与 POINTER_32 相关的头文件中看到 AXP 的一些遗迹

POINTER_32 在 Ntdef.h 和 Winnt.h 中定义。

<前><代码>#ifdef (__AXP64__)
#定义 POINTER_32 _ptr32
#别的
#定义 POINTER_32
#endif

警告C4244

__AXP64__ 适用于 Alpha AXP。即使 Windows 不再在该平台上运行,您也可以在 Ntdef.h 和 Winnt.h 中找到许多对 Alpha AXP 的其他引用。

因此,还有 POINTER_SIGNEDPOINTER_UNSIGNED 宏,用于指定如何将 32 位地址扩展为 64 位地址。它们将扩展为 __sptr__uptr


另一种用法是在禁用 LARGEADDRESSAWARE 在 64 位应用程序中

与 Linux 中的 x32 ABI 完全相同,其中 long 和指针是32位宽

默认情况下,基于 64 位 Microsoft Windows 的应用程序具有数 TB 的用户模式地址空间。有关精确值,请参阅 Windows 和 Windows Server 的内存限制发布。但是,应用程序可以指定系统应为应用程序分配低于 2 GB 的所有内存。如果满足以下条件,则此功能对于 64 位应用程序是有益的:

  • 2 GB 地址空间就足够了。
  • 该代码有许多指针截断警告。
  • 指针和整数可以自由混合。
  • 代码具有使用 32 位数据类型的多态性。

所有指针仍然是 64 位指针,但系统确保每次内存分配都低于 2 GB 限制,因此,如果应用程序截断指针,则不会丢失重要数据。 指针可以被截断为 32 位值,然后通过符号扩展零扩展扩展为 64 位值。

虚拟地址空间

当设置 /LARGEADDRESSAWARE:NO 时 即使高 32 位没有有效值,指针的大小仍然是 64 位宽。因此,为了节省指针的内存,我们必须将它们声明为 POINTER_32

请参阅如何在 Windows 上检测 X32?

My guest is that it was originally created for VLM (Very Large Memory) in Alpha AXP, because Windows NT for Alpha is the first Windows with some 64-bit support. The OS is still 32-bit but it has the VLM API for applications to allocate large 64-bit memory if necessary, hence there must be some way to declare both 32 and 64-bit pointers in the same program

VLM returns POINTER_64 that the app has to store. POINTER_32/__ptr32 are used by default, and POINTER_64/__ptr64 will be used in 64-bit handling code

You can still even see some relics of AXP in Windows documentation and header files related to POINTER_32

POINTER_32 is defined in Ntdef.h and Winnt.h.

#ifdef (__AXP64__)
#define POINTER_32 _ptr32
#else
#define POINTER_32
#endif

Warning C4244

__AXP64__ is meant for Alpha AXP. You can also find lots of other references to Alpha AXP in Ntdef.h and Winnt.h even though Windows no longer runs on that platform

Because of this there are also POINTER_SIGNED and POINTER_UNSIGNED macros to specify how the 32-bit address is extended to the 64-bit one. They'll be expanded to __sptr and __uptr


Another usage would be for 32-bit pointers when disabling LARGEADDRESSAWARE in a 64-bit application

It's exactly the same as x32 ABI in Linux where long and pointers are 32-bit wide

By default, 64-bit Microsoft Windows-based applications have a user-mode address space of several terabytes. For precise values, see Memory Limits for Windows and Windows Server Releases. However, applications can specify that the system should allocate all memory for the application below 2 gigabytes. This feature is beneficial for 64-bit applications if the following conditions are true:

  • A 2 GB address space is sufficient.
  • The code has many pointer truncation warnings.
  • Pointers and integers are freely mixed.
  • The code has polymorphism using 32-bit data types.

All pointers are still 64-bit pointers, but the system ensures that every memory allocation occurs below the 2 GB limit, so that if the application truncates a pointer, no significant data is lost. Pointers can be truncated to 32-bit values, then extended to 64-bit values by either sign extension or zero extension.

Virtual Address Space

When setting /LARGEADDRESSAWARE:NO the size of pointers are still 64-bit wide even though the high 32 bits has no significant values. Therefore to save memory for the pointer we must declare them as POINTER_32

See How to detect X32 on Windows?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文