为什么即使sizeof相同,指针也不能适合不同类型的变量?

时间:2019-04-08 12:03:39

标签: c++ pointers types casting strong-typing

为什么任何指针的大小是4或8个字节,但不能容纳任何其他变量?尝试为双指针分配int指针值时出现错误。

int          *int_ptr{nullptr};
float        *float_ptr{nullptr};
double       *double_ptr{nullptr};
long double  *long_double_ptr{nullptr};
string       *string_ptr{nullptr};
vector<int>   *vector_ptr{nullptr};

cout << "sizeof int pointer is " << sizeof int_ptr;    //8 or 4
cout << "sizeof float pointer is " << sizeof float_ptr;    //8 or 4
cout << "sizeof double pointer is " << sizeof double_ptr;    //8 or 4
cout << "sizeof double double pointer is " << sizeof long_double_ptr;    //8 or 4
cout << "sizeof string pointer is " << sizeof string_ptr;    //8 or 4
cout << "sizeof vector int pointer is " << sizeof vector_ptr;  //8 or 4

double double_num{1020.7};
double_ptr = &int_ptr;      //cannot convert ‘int**’ to ‘double*’ in assignment

3 个答案:

答案 0 :(得分:3)

C ++是一种静态类型的语言。该语言通过拒绝不相关类型之间的任意转换来增强类型安全性并保护您避免错误。类型的含义并不能仅通过大小来完全描述。

如果地址包含类型为int*的对象,则int**可以指向该对象。假定该地址包含一个int*类型的对象,它就不可能也包含一个double类型的对象,因此没有有意义的方法将这些指针之一转换为另一个指针。

答案 1 :(得分:0)

指针是地址。 假设您有两个地址:

  1. 53条主要大街
  2. 转弯道85号

第一个地址是一间两卧室小房子的地址。 第二个地址是到一个豪宅,23个卧室,10个浴室等...

您不能指望所有居住在大厦中的人都会搬进小屋吗? 但猜猜怎么了?在邮局,它们的盒子大小是一样的! 这就是他们的工作方式。他们只是告诉您在哪里可以找到您的变量。 Thay不是容器

答案 2 :(得分:0)

此代码是非法的,因为没有"implicit conversion"&int_ptrdouble_ptr的映射,其中“隐式转换”被定义为:

  

在上下文中使用某种类型T1的表达式时执行,该表达式不接受该类型,但接受某种其他类型的T2;特别是:

     
      
  • 当调用以T2作为参数声明的函数时,将该表达式用作自变量时;
  •   
  • 当表达式用作需要T2的运算符的操作数时;   初始化类型为T2的新对象时,包括返回T2的函数中的return语句;
  •   
  • 在switch语句中使用表达式时(T2是整数类型);
  •   
  • 在if语句或循环中使用表达式时(T2是布尔值)。   仅当存在从T1T2的明确的隐式转换序列时,程序的格式正确(编译)。
  •   

I initially suggested您使用了reinterpret_cast,但由于在类型之间使用reinterpret_cast的结果是合法的,仅当类型之间的区别仅在于它们的符号,转换为的类型是byte*char*unsigned char*,或者类型是“相似”,定义为:

  
      
  • 它们是同一类型;或
  •   
  • 它们都是指针,并且指向的类型相似;或
  •   
  • 它们都是指向相同类的成员的指针,并且指向的成员的类型相似;或
  •   
  • 它们都是相同大小的数组,或者都是边界未知的数组,并且数组元素类型相似。
  •   

如您所见,这些情况都不适用于希望从int* int_ptr的地址强制转换为double* double_ptr的地址。对于我来说,很难预测您在strongly typed language中使用这种类型的转换的用例,但是也许您正在寻找void*?它可能指向或者有效的int**,在这种情况下,您可以像这样初始化它:const void* ptr = reinterpret_cast<void*>(&int_ptr)或有效的double*,在这种情况下您要初始化就像这样:const void* ptr = reinterpret_cast<void*>(double_ptr)。当然,要使用ptr,您需要一个变量来告诉您它包含哪种类型,例如:

if(is_int) {
    // recover int** (reinterpret_cast<const int* const*>(ptr)) and operate on it
} else {
    // recover double* (reinterpret_cast<const double*>(ptr)) and operate on it
}

Live Example

在这一点上,我应该承认这个答案有些人为的。在使用此代码的任何地方,一个更好的解决方案很可能是模板。