在C++中投射指针

Casting pointers in C++?

本文关键字:指针 C++      更新时间:2023-10-16

运行此代码将返回我认为是realPtr地址的整数值。

我还是C++的新手,我想知道-是否可以从一个数据类型的指针转换到另一个,并且指定值的指针变量仍然会打印出正确的值(即*integerPtr打印出2)?

代码段

double real = 2.0;
double *realPtr = ℜ
int *integerPtr;
integerPtr = ((int*)&realPtr);
cout << *integerPtr << endl;

输出

1606416424

谢谢!

这里有三种完全不同的类型:

  • 指针指向内存中的任何位置。每个指针基本上都是相同的类型,但它们被视为不同的类型,这取决于您声明它们指向的
  • int和double是表示整数和实数值的类型;表示相同数值(例如2)的整数和双精度将不具有定义整数和浮点数字如何存储在存储器中的相关标准所规定的相同二进制内容

由于每个指针本质上都是相同的类型,因此可以将一种指针强制转换为任何其他类型。假设您有自己的Foo类,它与表示数值无关。你仍然可以这样做:

int* p_int = 2;
Foo* p_foo = (Foo*) p_int;

这是合法的,但这很可能会导致错误,除非Foo对象的内存表示类似于int。

如果要将int强制转换为double,则必须强制转换数据,而强制转换指针则没有任何作用。这就是为什么在C++11中有几个具有不同名称的类型转换,使用它们被认为是一种很好的做法,因为这样做可以明确地表达您想要做的事情。在你的情况下,你可能想要两种不同的东西之一

重新解释列表(_C)

将指向int的指针转换为指向double的指针,这意味着除了告诉编译器它可以安全地假设所指向的数据可以被视为double之外,基本上什么都不做。编译器会这样做,您有责任确保情况确实如此。这种类型的强制转换被认为是最危险的,因为众所周知,程序员是不可信任的。它被称为interpret_cast:

int* p_int = 2;
Foo* p_foo = reinterpret_cast<int>(p_int); 

与上面的代码相同,但我们在可怕的"represet_cast"中表达了危险。p_int和p_foo具有相同的值,除了表示我们现在将整数的地址视为foo的地址之外,我们什么也没做。

Static_cast

如果你想要一个真正的强制转换,你必须对数据进行操作,而不是对指针进行操作。通过编译器所知的任何方式将一种类型的数据转换为另一种类型,称为static_cast。这可能就是你想在这里做的:

int i = 2;
p_int = &i;
double d = static_cast<double>(i);
p_double = &d; //p_int and p_double have different values since they point to different objects.

编译器将查找从int到double的转换函数,如果找不到,就会对您大喊大叫。

当然,只使用指针做完全相同的事情并没有错,尽管这会使代码的可读性稍差(你应该警惕使用指针,这样做是有充分理由的):

int* p_i = 2;
int* p_d = static_cast<double>(*p_i) // p_d is a pointer to a double initialized to the value obtained after converting the int pointed to by p_i

float/dobule和integer数据类型的内部表示方式不同。在32位PC中,Integer将占用4个字节,而double将占用8个字节。

此外,您的代码中还有一个严重的错误。

double real = 2.0;
double *realPtr = &real;
int *integerPtr;
integerPtr = ((int*)&realPtr);
cout << *integerPtr << endl;

在上面的代码中,请参见粗体行。在那里,您声明了一个指向名为"integerPtr"的整数的指针。但实际值存储的指针地址为双精度。ie&realPtr是double**(指向包含double类型值的指针的指针)。然后您尝试使用*integerPtr打印值。

所以我更改了你的代码如下,它给出了一个值0。

double real = 2.0;
double *realPtr = &real;
int *integerPtr;
integerPtr = ((int*)realPtr);
std::cout << *integerPtr << std::endl;