打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
c、c++指针和整型的互相转换

c语言:

Noncompliant Code Example(不兼容的代码示例)

The size of a pointer can be greater than the size of an integer, such as in an implementation where pointers are 64 bits and unsigned integers are 32 bits. This code example is noncompliant on such implementations because the result of converting the 64-bit ptr cannot be represented in the 32-bit integer type:

void f(void) {

char *ptr;

/* ... */

unsigned int number = (unsigned int)ptr;

/* ... */

}

Compliant Solution(兼容的代码示例)

Any valid pointer to void can be converted to intptr_t or uintptr_t and back with no change in value (seeINT36-EX2). The C Standard guarantees that a pointer to void may be converted to or from a pointer to any object type and back again and that the result must compare equal to the original pointer. Consequently, converting directly from a char * pointer to a uintptr_t, as in this compliant solution, is allowed on implementations that support the uintptr_t type.

#include

void f(void) {

char *ptr;

/* ... */

uintptr_t number = (uintptr_t)ptr;

/* ... */

}

使用intptr_t和uintptr_t才是兼容的,就死一套代码同时兼容32位和64位的操作系统。

 

intptr_t和uintptr_t

这两个数据类型是ISO C99定义的,具体代码在linux平台的/usr/include/stdint.h头文件中。

该头文件中定义intptr_t和uintptr_t这两个数据类型的代码片段如下:

    /* Types for `void *' pointers.  */
    #if __WORDSIZE == 64
    # ifndef __intptr_t_defined
    typedef long int        intptr_t;
    #  define __intptr_t_defined
    # endif
    typedef unsigned long int    uintptr_t;
    #else
    # ifndef __intptr_t_defined
    typedef int            intptr_t;
    #  define __intptr_t_defined
    # endif
    typedef unsigned int        uintptr_t;
    #endif

在64位的机器上,intptr_t和uintptr_t分别是long int、unsigned long int的别名;在32位的机器上,intptr_t和uintptr_t分别是int、unsigned int的别名。

那么为什么要用typedef定义新的别名呢?我想主要是为了提高程序的可移植性(在32位和64位的机器上)。很明显,上述代码会根据宿主机器的位数为intptr_t和uintptr_t适配相应的数据类型。
 

 

c++语言:

reinterpret_cast<type-id> (expression)

type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。

type-id是转换后的类型,expresion是转换前的。

 

static_cast 与 reinterpret_cast

reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它。我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的。(这句话是C++编程思想中的原话)

static_cast和reinterpret_cast的区别主要在于多重继承,比如

1

2

3

4

5

6

7

8

9

10

11

class A {

    public:

    int m_a;

};

 

class B {

    public:

    int m_b;

};

 

class C : public A, public B {};

那么对于以下代码:

1

2

C c;

printf("%p, %p, %p", &c, reinterpret_cast<B*>(&c), static_cast <B*>(&c));

前两个的输出值是相同的,最后一个则会在原基础上偏移4个字节,这是因为static_cast计算了父子类指针转换的偏移量,并将之转换到正确的地址(c里面有m_a,m_b,转换为B*指针后指到m_b处),而reinterpret_cast却不会做这一层转换。

总结:reinterpret_cast用于指针和整型之间的转换是没有问题,如果用于子类和父类类型方面的转换,会有问题。如果需要在子类和父类指针之间的转换,要用static_cast。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
You Can't Always Hash Pointers in C « null program
intptr
C++类型转换
C++中四种类型转换方式
C语言指针的长度和类型深入分析
LevelDB源码剖析之Varint | 赖明星
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服