【问题标题】:Why can't we directly assign arr to pointer to array为什么我们不能直接将 arr 分配给指向数组的指针
【发布时间】:2021-06-02 03:43:45
【问题描述】:

我有一个由 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

【问题讨论】:

  • arr 衰减为 int*&arr 的类型为 int (*)[5]。所以类型检查做得很好。
  • arr&arr 是同一个地址,但不是同一种类型。
  • 你能解释一下这在 C 和 C++ 中有什么不同吗?在我看来,这在 c 和 c++ 中是一样的
  • C 中没有错误,这有区别:godbolt.org/z/hf5PKK
  • 它只是 c 给出警告。和 c++ 错误..所以两者都解释这是错误的,所以我认为标签没有错,任何知道 c ,c++ 的人都可以解释它..所以没有语言标签垃圾邮件的基础..

标签: c++ c pointers implicit-conversion explicit-conversion


【解决方案1】:

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

在此声明中

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;

在这种情况下&amp;a&amp;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 整数*[5];

然后在这个表达式中使用操作符 new

new int*[5]

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

【讨论】:

【解决方案2】:

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

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&amp;x 很可能具有相同的值是正确的,因此将x 分配给指针而不是&amp;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-08-09
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    相关资源
    最近更新 更多