如何将指针转换为整数

16

我试图将一个地址的值存储在非指针类型的整型变量中,但是当我尝试进行类型转换时,编译器报错“从'int*'到'int'的无效转换”。这是我正在使用的代码:

#include <cstdlib>
#include <iostream>
#include <vector>

using namespace std;

vector<int> test;

int main() {
    int *ip;
    int pointervalue = 50;
    int thatvalue = 1;

    ip = &pointervalue;
    thatvalue = ip;

    cout << ip << endl;

    test.push_back(thatvalue);

    cout << test[0] << endl;
    return 0;
}

从你的代码中,存储指针向量和打印它们是同一件事。 - chris
1
你为什么要这样做?仅仅进行转换并不是很便携(而且并非每个环境都有uintptr_t),你可能想要对结果进行的任何算术运算都可以使用指针更容易地完成,甚至更不易于移植。 - user395760
如果您将指针值转换为整数类型,那么很有可能您正在做一些错误的事情。如果您正确地执行此操作(并且如果机器具有足够大的某些整数类型来保存结果而不会丢失信息),则这是合法的转换,但99%的时间最好将指针视为指针。如果您告诉我们您希望使用整数完成的指针值的操作,也许我们可以帮助您在不进行转换的情况下完成它。 - Keith Thompson
6个回答

29

int 可能不足以存储指针。

你应该使用 intptr_t。这是一个整数类型,明确足够大以容纳任何指针。

    intptr_t thatvalue = 1;

    // stuff

    thatvalue = reinterpret_cast<intptr_t>(ip);
                // Convert it as a bit pattern.
                // It is valid and converting it back to a pointer is also OK
                // But if you modify it all bets are off (you need to be very careful).

我不明白,int 不足以容纳任何指针? 但是,int 的大小恰好为4294967295,这相当于十六进制的FFFFFFFF,难道指针不只是保持在00000000和FFFFFFFF之间某个数字的地址吗? 那不是意味着int足够大来存放指针吗? 这是我对此工作原理的理解,请在我错误的地方进行更正。 - user1934608
@user1934608:不能保证它足够大。在某些系统上,它可能足够大,但并非所有系统都是如此。例如,一些64位系统需要64位指针,但它们的整数可能只有32位(尽管有些会有64位整数,这完全取决于系统)。但是intptr_t将始终足够大,以容纳指针而不会丢失信息。注意:我使用的是Macbook,我更改了您的代码以使用thatvalue = reinterpret_cast<int>(ip),但我收到错误消息:“error: cast from ‘int*’ to ‘int’ loses precision”。 - Martin York
@LokiAstari:重要的是要区分int(它是一种特定类型)和“整数”(它们是一组类型,从charlong long int不等)。例如,一个系统可能有一个32位的int类型和一个64位的整数类型(称为longlong long)。 - Keith Thompson

8
你可以这样做:
int a_variable = 0;

int* ptr = &a_variable;

size_t ptrValue = reinterpret_cast<size_t>(ptr);

9
使用<cstdint>中的std::uintptr_t - GManNickG
@GManNickG... 谢谢,我之前不知道这个。我使用 size_t 是因为它能够适应平台上的指针大小。 - sgarizvi
4
size_t 可能可以使用。但是 intptr_t 明确设计为一个整数类型,可以保存指针值(而不会丢失信息)。 - Martin York

4

你为什么要这样做?其实你只需要将C代码强制转换即可:

thatvalue = (int)ip;

如果您正在编写C++代码,最好使用reinterpret_cast

3
我建议使用C++风格的强制类型转换,例如reinterpret_cast,而不是旧式的C强制类型转换。 - Mr.C64
1
reinterpret_cast 比 C 风格转换更好,原因:https://dev59.com/nWsz5IYBdhLWcg3wiIWe - benjarobin
我刚刚尝试了一下,我认为它给出的输出与指针地址不同。它打印了:"2293616"和"0x22ff70",我所做的只是将行thatvalue = ip;替换为thatvalue = (int)ip;,我做错了什么吗?编辑:算了,我刚刚谷歌了一个十六进制转十进制的转换器,找到了我的错误所在...哈哈 - user1934608
这是相同的数字:2293616 = 0x22ff70。 - benjarobin
2
这也注定会失败。int 可能不够大,无法在 64 位系统上存储指针。 - Martin York

4

我建议使用reinterpret_cast

thatvalue = reinterpret_cast<intptr_t>(ip);

3
使用reinterpret_cast是正确的,但不适用于int类型。 - Martin York
我假设在 OP 的机器上,int 足够大以存储指针,但我同意你的观点,一般来说最好使用 intptr_t,例如对于某些 64 位系统,因此我已更新我的答案。谢谢。 - Mr.C64

0

我能够使用C联合语句来实现你所寻求的功能。当然,这将取决于编译器,但在我的环境下它像你预期的那样工作(Linux,g++)。

union {
    int i;
    void *p;
} mix;

mix.p = ip;
cout << mix.i << endl;

在我的特定实例中,我的int是32位的,指针是48位的。当分配指针时,整数值i将代表指针最低的32位。


0

由于int *ip;是指向整数的指针,而int thatvalue = 1;是一个整数,假设您想要将存储在ip所指向地址中的值分配给thatvalue,请将thatvalue = ip;更改为thatvalue = *ip;(请注意添加解引用运算符*以访问与指针地址处的值等效的值)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接