Skip to content

Commit a897ad6

Browse files
authored
Merge pull request #5860 from jdpatdiscord/main
clarify behavior of __ptr32/__ptr64 example
2 parents 4e0d556 + 5b6b51b commit a897ad6

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

docs/cpp/ptr32-ptr64.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
---
22
description: "Learn more about: __ptr32, __ptr64"
33
title: "__ptr32, __ptr64"
4-
ms.date: "10/09/2018"
4+
ms.date: 12/16/2025
55
f1_keywords: ["__ptr32_cpp", "__ptr64_cpp", "__ptr32", "__ptr64", "_ptr32", "_ptr64"]
66
helpviewer_keywords: ["__ptr64 keyword [C++]", "_ptr32 keyword [C++]", "ptr32 keyword [C++]", "ptr64 keyword [C++]", "_ptr64 keyword [C++]", "__ptr32 keyword [C++]"]
7-
ms.assetid: afb563d8-7458-4fe7-9c30-bd4b5385a59f
87
---
98
# __ptr32, __ptr64
109

11-
**Microsoft Specific**
10+
**Microsoft specific**
1211

13-
**`__ptr32`** represents a native pointer on a 32-bit system, while **`__ptr64`** represents a native pointer on a 64-bit system.
12+
Use **`__ptr32`** to represent a native pointer on a 32-bit system. Use **`__ptr64`** to represent a native pointer on a 64-bit system.
13+
14+
The `__ptr32` and `__ptr64` modifiers are Microsoft-specific extensions for interop scenarios. For standard 32-bit (x86) or standard x64 code, use native pointers, instead.
1415

1516
The following example shows how to declare each of these pointer types:
1617

@@ -19,17 +20,22 @@ int * __ptr32 p32;
1920
int * __ptr64 p64;
2021
```
2122

22-
On a 32-bit system, a pointer declared with **`__ptr64`** is truncated to a 32-bit pointer. On a 64-bit system, a pointer declared with **`__ptr32`** is coerced to a 64-bit pointer.
23+
On a 32-bit system, a pointer declared with **`__ptr64`** is treated as a 32-bit pointer and truncates the upper 32 bits of any 64-bit address assigned to it. On a 64-bit system, a pointer declared with **`__ptr32`** is treated as a 32-bit pointer and truncates the upper 32 bits of any 64-bit address assigned to it. This truncation can lead to an invalid pointer if the 64-bit address is above 4GB.
2324

2425
> [!NOTE]
25-
> You cannot use **`__ptr32`** or **`__ptr64`** when compiling with **/clr:pure**. Otherwise, Compiler Error C2472 will be generated. The **/clr:pure** and **/clr:safe** compiler options are deprecated in Visual Studio 2015 and unsupported in Visual Studio 2017.
26+
> You can't use **`__ptr32`** or **`__ptr64`** when compiling with **`/clr:pure`**. Otherwise, the compiler generates error C2472. The **/clr:pure** and **/clr:safe** compiler options are deprecated in Microsoft Visual Studio 2015 and unsupported in Microsoft Visual Studio 2017.
2627
27-
For compatibility with previous versions, **_ptr32** and **_ptr64** are synonyms for **`__ptr32`** and **`__ptr64`** unless compiler option [/Za \(Disable language extensions)](../build/reference/za-ze-disable-language-extensions.md) is specified.
28+
For compatibility with previous versions, **`_ptr32`** and **`_ptr64`** are synonyms for **`__ptr32`** and **`__ptr64`** unless you specify compiler option [/Za \(Disable language extensions)](../build/reference/za-ze-disable-language-extensions.md).
2829

2930
## Example
3031

3132
The following example shows how to declare and allocate pointers with the **`__ptr32`** and **`__ptr64`** keywords.
3233

34+
This code works on x86 but might crash on x64.
35+
36+
- It works when compiled for 32-bit because **`__ptr64`** pointers are treated as 32-bit pointers on x86. On x86 (32-bit), `malloc` returns a 32-bit address which fits in `p64`.
37+
- It might crash when compiled for 64-bit because on x64, `malloc` returns a 64-bit pointer which is truncated to 32 bits by this line: `p32 = (int* __ptr32)malloc(4);`. Truncating a 64-bit address to a 32-bit address could result in an invalid pointer if the allocation happened above 4GB. In that case, `*p32 = 32` could attempt to access a truncated address that isn't part of your process's address space, causing an access violation. Even if it works once, it could fail later if the memory allocator returns a higher address.
38+
3339
```cpp
3440
#include <cstdlib>
3541
#include <iostream>
@@ -38,22 +44,22 @@ int main()
3844
{
3945
using namespace std;
4046

41-
int * __ptr32 p32;
42-
int * __ptr64 p64;
47+
int* __ptr32 p32;
48+
int* __ptr64 p64;
4349

44-
p32 = (int * __ptr32)malloc(4);
45-
*p32 = 32;
50+
p64 = (int* __ptr64)malloc(4);
51+
*p64 = 64; // Works on x86 and x64
52+
cout << *p64 << endl;
53+
54+
p32 = (int* __ptr32)malloc(4);
55+
*p32 = 32; // Works on x86. Possible exception on x64
4656
cout << *p32 << endl;
47-
48-
p64 = (int * __ptr64)malloc(4);
49-
*p64 = 64;
50-
cout << *p64 << endl;
5157
}
5258
```
5359

5460
```Output
55-
32
5661
64
62+
32
5763
```
5864

5965
**END Microsoft Specific**

0 commit comments

Comments
 (0)