【问题标题】:Arrays - Why is the subscript operator tied to the identifier?数组 - 为什么下标运算符与标识符相关联?
【发布时间】:2016-11-17 22:56:58
【问题描述】:

为什么数组的下标运算符要绑定标识符?

因为我们写的时候:

int a[5];

a 实际上是“int[5]”类型

这禁止使用以下内容:

typedef int[3][3] matrix_t;
....
void foo(matrix_t my_matrix){
  ....
}

实际实施有什么好处?

我真的很想拥有这个功能还是我错过了什么?

【问题讨论】:

  • typedef int matrix_t[3][3]
  • using matrix_t = int[3][3]
  • 这只是 c++ 对吧?
  • 挑一个.......
  • C 和 C++ 是不同的语言。请删除不相关的标签!

标签: c++ c arrays operators


【解决方案1】:

在 C 中,您可以按照使用方式键入变量。

它们有点像“冻结的表达式”。

所以

int x[5][2];

意味着您将使用x,首先在[] 中传递一个最大为5 的值,然后在[] 中传递一个最大为2 的值,然后将该值分配给@ 987654327@.

从某种意义上说,这重用了表达式解析引擎来输入内容。

typedef 就像声明一个变量一样工作,除非该变量将成为该类型的别名。所以不是

typedef int[3][3] matrix_t;

是的

typedef int matrix_t[3][3];

再次,这将重用变量声明解析/语法来定义类型别名。

在 C++11 中,using 的工作方式更像您可能想要的那样:

using matrix_t = int[3][3];

问题的最后一部分是 C 中的矩阵不能被复制或按值传递。 int[3][3] 类型作为函数参数变成int[3]* 类型——指向int[3]s 的指针。而且您不能返回 int[3][3] 类型的句点。

在 C++ 中,这是通过 std::array 修复的:

std::array< std::array< int, 3 >, 3 >

是一种与int[3][3] 布局兼容的类型(至少在实践中),但可以像值一样传递给函数/从函数传递。在 C 中你会这样做:

struct matrix {
  int data[3][3];
};

在内存中的布局与上面的std::array 相同,并且可以像值一样向函数传递/从函数传递。

【讨论】:

    【解决方案2】:

    这只是 C 语言开发早期的历史遗产。当时决定实体的声明应该模仿其未来的用法。因此,数组声明看起来类似于在表达式中使用数组的方式。这同样适用于函数声明、指针声明等。(指针声明中的* 也“绑定到标识符”)

    在现代 C++ 中,在某些情况下,您实际上可以使用新语法,它遵循您建议的逻辑。它适用于 typename 别名的 using-declarations(类似于经典的 typedef-declaration)

    using array_type = int[3];
    // Same as
    // typedef int array_type[3];
    

    或函数返回类型声明等上下文

    auto foo() -> int (*)[3]
    {
      ...
    
    // Same as
    // int (*foo())[3]
    

    【讨论】:

    • 每种语言都有其语法。不知道您所说的“遗产”是什么意思;这就是 C 的设置方式。该声明也适用于所有其他语言。
    • @Olaf:我只是在评论为什么语法在最初设置时就以这种方式设置的问题。你知道,我们没有收到来自外太空的石碑上的 C 语法。语法是人创造的。这就是为什么他们以这种特定的方式创建它(或者至少是一些消息来源关于“为什么”的说法)
    • 我的意思是“遗留”论点适用于每一种编程语言,包括相对较新的 Go、Rust 或 Swift。选择了一些语法,以后的版本必须使用它(一旦该语言至少有足够大的用户群)。
    猜你喜欢
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 1970-01-01
    • 1970-01-01
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多