C 中的数组是指针的语法糖吗?

Are arrays in C a syntactic sugar for pointers?

我们来看看下面的代码:

int arr[n];
// s.t. i<n
arr[i] = 12;
// s.t. i<n 
*(arr + i) = 12;

arr[i]*(arr+ i) 的语法糖吗?

是的,您可以说- 数组下标访问 与使用* 解引用的指针访问相同。

来自6.5.2.1p2 C11标准N1570

A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

决不会给您数组是指针的印象。有趣的是,当您应用 [] 时,数组会衰减为指向第一个元素的指针,并用于访问后续元素。

数组对象是另一回事 - 在某些情况下数组不会退化为指针。它们不是语法糖 - 你可以考虑一个例子 -

int p[] = {1, 2 ,3};
int *t = p;
size_t sz1 = sizeof p;
size_t sz2 = sizeof t;
printf("%zu %zu\n", sz1, sz2);

运行 这个,我会理解一些与你的问题更相关的东西。不能使用数组本身以外的东西来实现数组。数组访问与指针取消引用相同,但这并不意味着指针占据数组的位置,反之亦然。

C 编程的要点或红丸:

Arrays are arrays and pointers are pointers. They are different thing.


顺便说一句,如果 sizeof 欺骗了您一点 - 别担心,标准部分是这么说的。来自 6.3.2.1p3

Except when it is the operand of the sizeof operator, the _Alignof 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...

数组用作 sizeof 的操作数时不会转换为指针。就是这样。这就是为什么你得到你在前面的代码片段中得到的东西。

是的,arr[i]*(arr+i) 相同,后者与 *(i+arr) 相同,后者又与 i[arr]

相同

来自 Fabio Turati 的评论: 有关详细信息,请参阅 "Why is a[5] == 5[a]"

绝对不会!要看到这一点,只需在示例中用指针替换数组:

int *arr;
// s.t. i<n
arr[i] = 12;
// s.t. i<n 
*(arr + i) = 12;

这可以正常编译,但它是未定义的行为。它不能保证工作。事实上,没有什么这个程序可能会被认为是编译器中的错误。

数组就是数组;包含数据的类型。指针指向数据所在的位置。指针不包含实际数据,而数组包含。

在某些 情况下,数组名称的行为方式与指针相同。这并不能使两者完全相同。

例如,检查一下:

int arr[12];
int ptr;

ptr = arr; // Legal
printf("array size %ld\n", sizeof(arr)); // Usually prints 12*4=48
printf("pointer size %ld\n", sizeof(ptr)); // Depending on your arch, will likely print either 4 or 8.

是的,您可以使用 arr[i]/*(arr+i) 访问数组的元素。

你甚至可以对数组指针使用增量操作。 *ptr = &arr, ptr++

这意味着每次您将整数或增量添加到数组指针时,指针都会将(数据类型的大小)*i 添加到前一个指针。

严格来说,数组不是指针的语法糖。根据定义,“句法糖”是语言结构,它允许您编写更短/更清晰的等价于其他语言结构的语言。指针和数组的情况不同。指针是包含某个值的内存地址的变量。不同的是,数组是包含这些值本身的变量。但是,C 语法的构建方式允许您将指针视为数组第一个元素的地址并对其应用索引运算符。但我不会说这是语法糖,这是语言的基本语法。