【问题标题】:What's the difference between &table[0][0] and &table?&table[0][0] 和 &table 有什么区别?
【发布时间】:2021-02-13 10:55:24
【问题描述】:

我已经成功尝试将二维数组传递给函数,请参见下面的代码。我不明白:为什么我的“方法 C”(见下面的代码)不起作用?

&table[0][0] 和 &table 有什么区别?它们都指向同一个内存地址。前者作为传递给我的函数的参数,后者没有,错误消息:

"no known conversion from 'int (*)[3][2]' to 'int *' for 1st argument void print_table(int *table, const int ROWS, const int COLUMNS)

提前致谢!亚历克斯

#include <iostream>
void print_table(int *table, const int ROWS, const int COLUMNS)
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLUMNS; j++)
        {
            std::cout << table[i * COLUMNS + j] << "\t";
        }
        std::cout << "\n";
    }
}

int main()
{
    const int ROWS = 3;
    const int COLUMNS = 2;
    int table[ROWS][COLUMNS] = {{1,2},{3,4},{5,6}};

    std::cout << (int*)table << "\n";     // these 3 couts all deliver the same memory address      
    std::cout << &table[0][0] << "\n";    // these 3 couts all deliver the same memory address
    std::cout << &table << "\n";          // these 3 couts all deliver the same memory address

    print_table((int*)table, ROWS, COLUMNS);   // method A: Works.
    print_table(&table[0][0], ROWS, COLUMNS);  // method B: Works too.
    print_table(&table, ROWS, COLUMNS);        // method C: Doesn't work! Why?
    
    return 0;
}

【问题讨论】:

  • 编译器的错误信息给你一个非常易读的解释。你不清楚哪一部分? &amp;table 的类型是 int (*)[3][2],错误消息对此很有帮助。不能转换为int *。 C++ 不能以这种方式工作。 table[0][0] 是 int(好吧,int &amp;,学究式),所以 &amp;table[0][0] 是 int *。结束。
  • 打印表需要一个指向 int 的指针,而 &amp;table 是表的地址,它的类型为 int[3][2],因此您正在发送一个指向 [3][2] int 数组的指针。
  • 指向二维整数数组的指针。
  • 谢谢你们! @TonyTannius 你的添加让我明白了!
  • 阅读en.cppreference.com/w/c/language/array,它说的是数组到指针的转换,以及更多关于同一主题的c++特定部分en.cppreference.com/w/cpp/language/array

标签: c++ arrays pointers multidimensional-array pass-by-reference


【解决方案1】:

主要区别:实际指向的是什么,以及它的类型。

表达式&amp;table 指向数组table 本身,它的类型为int(*)[3][2]。

表达式&amp;table[0][0] 是指向子数组table[0] 中单个元素的指针,类型为int*。

“方法 A”起作用的原因,即使它是错误的,也是因为两个指针恰好指向同一个位置。

如果我们画出你的数组,那么它看起来像这样(添加了“指针”):

+-------------+-------------+--------------+------- ------+--------------+--------------+ |表[0][0] |表[0][1] |表[1][0] |表[1][1] |表[2][0] |表[2][1] | +-------------+-------------+--------------+------- ------+--------------+--------------+ ^ | &桌子 | &表[0] | &表[0][0]

我添加了&amp;table[0],因为这就是普通的table 将衰变到的内容。它将具有int(*)[2] 类型。这是您作为“方法 A”传递的指针。如果不强制转换为 int*,该方法也会失败。

一般来说:每当您需要进行 C 风格的转换(例如“方法 A”)时,您应该将其视为您做错了什么的标志。

简而言之:只有“方法B”才是真正正确的。

【讨论】:

  • 学究式地,由于指针算法,即使方法 B 也是 UB:int[ROWS][COLUMNS] != int[ROWS * COLUMNS]。
  • 我总结一下:我的“方法 A”是错误的,因为不推荐使用 C 风格的转换;我的“方法B”是“未定义的行为”,因为指针算术(我仍在试图绕开我的脑袋......)而我的“方法C”显然不起作用。那么你更喜欢的“方法 D”是什么?
猜你喜欢
  • 2019-07-20
  • 2020-02-01
  • 2021-06-05
  • 2016-03-23
  • 2021-06-16
  • 2020-01-24
  • 1970-01-01
  • 2012-09-23
相关资源
最近更新 更多