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

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

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

我假设读者了解指针算法的工作原理。

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

老师/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 下标运算符不需要数组?标准错了吗?我的老师/C书是不是糊涂了?

最佳答案

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

数组在表达式中使用时,总是“衰减”为指向第一个元素的指针(有一些异常(exception))。 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 都会被指向该数组中第一个元素的指针所取代。这被非正式地称为“数组衰减”。更多信息在这里: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) 并不重要——这是等效的代码。

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

关于c - 指针是否支持 "array style indexing"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55747822/

相关文章:

javascript - 如何使用 lodash 递归地从 JSON 中删除空对象

c++ - std::untialized_copy 是否有未定义的行为?

c - 带结构的指针算术

c++ - "this"指针上的指针运算

c++ - 大量文件的原子删除

c - C 中的免费通用链表 - 段错误

c++ - 返回 (a) 与返回 a

javascript - 在javascript中迭代json数组

c++ - 调用覆盖函数库

java - 如何将 java ArrayList 转换为数组?