指针是否支持"array style indexing"?

Do pointers support "array style indexing"?

(自答问答 - 这个问题不断弹出)

我假设 reader 知道指针算法的工作原理。

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

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

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

6.5.2.1 Array subscripting

Constraints

One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.

为什么 array 下标运算符不需要数组?标准错了吗?我的 teacher/C 书糊涂了吗?

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

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

Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.

意味着无论何时键入 arr[i],操作数 arr 都会被指向该数组中第一个元素的指针替换。这被非正式地称为 "array decaying"。更多信息在这里:What is array decaying?

因此,无论何时使用 [] 运算符,都是在指针上使用它。总是。

C 标准说这个运算符保证等价于指针运算 (C17 6.5.2.1/2):

The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).

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

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

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