【问题标题】:Do pointers support "array style indexing"?指针是否支持“数组样式索引”?
【发布时间】:2019-09-08 21:31:40
【问题描述】:

(自我回答的问答 - 这件事不断弹出)

我假设读者知道指针运算的工作原理。

int arr[3] = {1,2,3};
int* ptr = arr;
...
*(ptr + i) = value;

Teachers/C 书籍一直告诉我,我不应该像上面的例子那样使用 *(ptr + i),因为“指针支持数组样式索引”,我应该改用 ptr[i] = value;。那里没有争论 - 更容易阅读。

但是通过 C 标准,我发现没有所谓的“数组样式索引”。事实上,[] 运算符并不期望任一操作数是数组,而是指针或整数!

6.5.2.1 数组下标

约束

其中一个表达式的类型应为''指向完成对象的指针type'',另一个表达式应为整数类型,结果的类型为''type ''。

为什么 array 下标运算符不期望一个数组?标准错了吗?我的老师/C 书有问题吗?

【问题讨论】:

    标签: c arrays pointer-arithmetic subscript-operator array-indexing


    【解决方案1】:

    出于可读性原因,您确实应该使用ptr[i] 而不是*(ptr + i)。但除此之外,严格来说,[] 运算符实际上从未与数组操作数一起使用。

    当在表达式中使用时,数组总是“衰减”为指向第一个元素的指针(有一些例外)。 C17 6.3.2.1/3,强调我的:

    除非它是 sizeof 运算符的操作数,或一元 & 运算符,或者是用于初始化数组的字符串字面量,类型为 ''array of type'' 的表达式将转换为类型为“类型指针”的表达式,它指向数组对象的初始元素,并且不是左值。

    这意味着每当您键入arr[i] 时,操作数arr 都会被指向该数组中第一个元素的指针所取代。这被非正式地称为“阵列衰减”。更多信息在这里:What is array decaying?

    因此,每当您使用[] 运算符时,您都会在指针上使用它。总是。

    C 标准规定该运算符保证等价于指针算术 (C17 6.5.2.1/2):

    下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))

    所以每当我们输入arr[i] 时,它实际上会被*(arr+i) 默默地替换。其中arr 仍然是指向第一个元素的指针。

    这就是为什么你引用的描述告诉你 either 操作数可以是指针而另一个是整数。因为显然我们输入*(arr+i)*(i+arr) 并不重要——这是等效的代码。

    这反过来又允许我们编写像i[arr] 这样的混淆“笑话”代码,它实际上是有效的C 并且完全等同于arr[i]。但不要在实际应用中编写这样的代码。

    【讨论】:

    • 几十年来被要求写offset(register)的汇编语言程序员写i[array]可能会被原谅。
    • 我们可以写成 i[arr] 因为标准在 6.5.2.1 中使用术语“一个表达式...”而不是“第一个表达式...”
    猜你喜欢
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多