1

我有一个由 5 个整数组成的数组。arr 和 &arr 是相同的地址。那么为什么数字 2 给出编译错误并且 3 工作正常。

  int arr[5] = {1,2,3,4,5};
  1. int *p = arr;
  2. int (*p1)[5] = arr //Compilation Error
  3. int (*p1)[5] = &arr; //Works fine.
  
     arr = 0x61fdf0 and &arr= 0x61fdf0
4

2 回答 2

3

问题是初始化对象和初始化器有不同的指针类型,并且没有从一种指针类型到另一种指针类型的隐式转换。

在这份声明中

int (*p1)[5] = arr;

由于数组指示符隐式转换为指向其第一个元素的指针,因此初始化对象具有类型int ( * )[5],而初始化程序具有类型。int *

你必须写

int (*p1)[5] = &arr

或者例如

int ( *p1 )[5] = reinterpret_cast<int ( * )[5]>( arr );

这是一个演示程序。

#include <iostream>

int main() 
{
    int arr[5] = {1,2,3,4,5};   
    
    int ( *p1 )[5] = reinterpret_cast<int ( * )[5]>( arr );

    std::cout << "sizeof( *p1 ) = " << sizeof( *p1 ) << '\n';
    
    return 0;
}

程序输出为

sizeof( *p1 ) = 20

对象可以具有相同的值,但可以具有不同的类型。

考虑另一种情况。

假设您有一个结构类型的对象

struct A
{
    int x;
} a;

在这种情况下 &a&a.x具有相同的值,但表达式的类型不同。例如,您可能不会写

int *p = &a;

编译器将发出错误。但是你可以写

int *p = ( int * )&a;

或者

int *p = reinterpret_cast<int *>( &a );

这是一个演示程序。

#include <iostream>
#include <iomanip>

int main() 
{
    struct A
    {
        int x;
    } a = { 10 };
    
    std::cout << std::boolalpha << ( ( void * )&a.x == ( void * )&a ) << '\n';
    
    int *p = reinterpret_cast<int *>( &a );
    
    std::cout << "*p = " << *p << '\n';
    
    return 0;
}

程序输出为

true
*p = 10

至于您在评论中的另一个问题

你能用简单的语言对此进行解码以理解 int** p = new int*[5];

然后在这个表达式中使用运算符 new

new int*[5]

为具有 5 个类型元素的数组分配了内存int *。该表达式返回一个指向数组第一个元素的指针。指向类型对象int *(已分配数组的元素类型)的指针将具有 type int **

于 2021-03-03T14:35:42.527 回答
0

简单来说,就是这个抛出编译错误的原因是一样的:

int main()
{
    int x = 5;
    int *p = x;
}

当您有一个为对象类型指定的指针时,您应该分配该类型对象的地址。话虽这么说,虽然上面的代码没有意义,但下面的代码可以:

int main()
{
    int x = 5;
    int *p = &x;
}

这适用于数组,就像它适用于其他任何东西一样。

int main()
{
    int x[5] = {1, 2, 3, 4, 5};
    int (*p)[5] = x; // Compilation error.
    int (*p)[5] = &x; // Does exactly what it should.
}

您说得对,x并且&x很可能具有相同的值,因此分配x给指针而不是&x应该有效且有意义。虽然从技术角度来看确实有意义,但从语义角度来看却没有意义。c++ 语言优先考虑语义以帮助程序员避免错误。这是一个例子:

int main()
{
    int x = 0x72fe1c; // Let's imagine that 0x72fe1c just so happens to be the address of x.
    // x is an int variable holding a value which just so happens to be equal to its address.
    int *p = x; // This is never desirable; thank the compiler for telling you something is wrong.
}

从技术角度来看,上面的代码是有意义的。x保存一个恰好等于它自己的内存地址的值,那么将其值分配给指针有什么危害?“危害”在于 C++ 程序员在实际情况中永远不会想要这个,因为 C++ 比汇编高一级;你不应该使用这样的内存地址。因此,编译器禁止您执行此类代码以帮助您避免错误。

于 2021-03-03T16:47:27.450 回答