分享

c、c++指针和整型的互相转换...

 wuxinit_ 2021-04-15

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。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多