方括号在 C 中如何工作?

How do square brackets work in C?

我刚刚开始使用 C,我正在尝试了解基础知识。大量的教程会告诉你一些事情并且让你相信它而没有任何真正的解释而且我找不到任何人类可读的答案。

在以下:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int *a;

  a = malloc(5 * sizeof(int));

  a[2] = 4;

  printf("%d\n", a[0]); // Prints 0
  printf("%d\n", a[2]); // Prints 4

  return 0;
} 

我没有明确地将 int *a 声明为指向数组的指针,但是如果我给它分配一些内存,我就可以像 had[=27 那样使用 a =] 将其声明为数组。声明一个带有方括号的指针只是我在下面所做的事情的快捷方式吗?方括号实际上是在做一些指针运算吗?

厚脸皮第二题

为什么内存地址分配给a而不是*a

Are square brackets actually doing some pointer arithmetic?

a[b] 等同于 *(a + b)。所以是的,它是指针算术。它首先将指针偏移 b 然后访问该内存位置,就像数组一样。

Why is the memory address assigned to a and not *a?

内存地址存放在a中,因为a是指针,指针存放内存地址。 *a是那个内存地址的数据。

Is declaring a pointer with square brackets just a shortcut for what I've done below?

当然不是!数组和指针是两个完全不同的东西。 int a[5];,这里 a 的类型是 int[5],而 int *b; b 的类型是 int*。在许多情况下,前者会衰变成后者。这称为阿里衰减。阅读更多相关信息 here

Are square brackets actually doing some pointer arithmetic?

是的,当你做 a[3] 时,真正发生的是 *(a + 3),即 a 衰减为 int*,剩下的只是指针运算,即指向添加了 a3 * sizeof(int) 的第一个元素。

Why is the memory address assigned to a and not *a?

我认为您混淆了标识符和应用于变量的运算符。指针只是另一个变量;所有变量名都应遵循标识符的规则,即来自标准:

An identifier is an arbitrarily long sequence of letters and digits.

虽然运算符 * 取消引用它所应用的指针,并且 returns 基于指针类型的结果。所以内存地址总是赋值给a这个变量。 a 指向的内存地址处的值将始终由 *a.

引用

I have not explicitly declared int *a as a pointer to an array, but if I allocate it some memory, I can then use a like I had declared it as an array. Is declaring a pointer with square brackets just a shortcut for what I've done below?

类似,但不是。 int *aa 声明为指向 int 的指针。 int b[5] 分配 space 5 int 秒,将 b 声明为 指向 int 数组的常量指针- int 引用(在大多数情况下可以被视为指向 int 的常量指针),并将 b 定义为指向分配的 space 的指针。因此,int b[5]int *a 做得更多,这也意味着 int *aint b[5] 更灵活。例如,您可以增加 a,但不能增加 b

malloc 在堆上分配内存。 int b[5],如果是全局变量,将在程序的数据段中(即按字面意义编译成可执行文件)。如果是本地的,它将在堆栈上分配。同样,相似但不同。

Are square brackets actually doing some pointer arithmetic?

在声明中,没有。当您 使用 指针变量时,是的:x[y]*(x + y) 相同。所以 a[1]*(a + 1) 相同,后者与 *(1 + a) 相同,后者又与 1[a] 相同(但请不要使用最后一个)。

Why is the memory address assigned to a and not *a?

厚颜无耻地回答一个厚颜无耻的问题:因为你写的是 a = ... 而不是 *a = ...

编辑:John Bode 给出了一个有用的指针(呵呵):常量指针和数组引用不是一回事,尽管它们非常相似。一方面,sizeof(...) 会给出不同的结果。

Are square brackets actually doing some pointer arithmetic?

是的。括号可以应用于任何指针,而不仅仅是数组。他们为指针算法指针解引用提供了shorthand。您的代码基本上是这样做的:

int *a = malloc(5 * sizeof(int));

*(a+2) = 4;

printf("%d\n", *(a+0));
printf("%d\n", *(a+2));

这实际上相当于这样做:

int *a = malloc(5 * sizeof(int));

*((int*)(((unsigned long)a)+(2*sizeof(int)))) = 4;

printf("%d\n", *((int*)(((unsigned long)a)+(0*sizeof(int)))));
printf("%d\n", *((int*)(((unsigned long)a)+(2*sizeof(int)))));

为什么内存地址分配给a而不是*a?

因为 malloc() returns 一个 address ,您使用 = 运算符将其分配给(存储在)指针变量 a

通常我们将 malloc() 返回的 address 存储在指针变量中,就像您对语句 a = malloc(5 * sizeof(int));.

的处理方式一样

如果您尝试将 malloc() 返回的地址存储在非指针变量中,则会遇到问题。