C 数组第一个元素的地址存储在哪里?

C 数组第一个元素的地址存储在哪里?,c,arrays,C,Arrays,我在玩C,我刚刚发现a和&产生的结果与数组第一个元素的地址相同。通过浏览这里的主题,我发现它们的格式不同。所以我的问题是:这个地址存储在哪里?它不存储在任何地方-它是根据需要计算的 除非它是sizeof、\u Alignof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“T的N元素数组”类型的表达式将转换为“指向T的指针”类型的表达式(“衰减”),表达式的值是数组第一个元素的地址 当您声明一个数组时,如 T a[N]; // for any non-function

我在玩C,我刚刚发现a和&产生的结果与数组第一个元素的地址相同。通过浏览这里的主题,我发现它们的格式不同。所以我的问题是:这个地址存储在哪里?

它不存储在任何地方-它是根据需要计算的

除非它是
sizeof
\u Alignof
或一元
&
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“T的N元素数组”类型的表达式将转换为“指向
T
的指针”类型的表达式(“衰减”),表达式的值是数组第一个元素的地址

当您声明一个数组时,如

T a[N];  // for any non-function type T
你在记忆中得到的是

+---+
|   | a[0]
+---+
|   | a[1]
+---+
 ...
+---+ 
|   | a[N-1]
+---+

就这样。没有为任何指针具体化存储。相反,当您在任何表达式中使用
a
时,编译器将计算
a[0]
的地址,并使用该地址。

它不会存储在任何位置,而是根据需要进行计算

除非它是
sizeof
\u Alignof
或一元
&
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“T的N元素数组”类型的表达式将转换为“指向
T
的指针”类型的表达式(“衰减”),表达式的值是数组第一个元素的地址

当您声明一个数组时,如

T a[N];  // for any non-function type T
你在记忆中得到的是

+---+
|   | a[0]
+---+
|   | a[1]
+---+
 ...
+---+ 
|   | a[N-1]
+---+

就这样。没有为任何指针具体化存储。相反,当您在任何表达式中使用
a
时,编译器将计算
a[0]
的地址并使用它。

这是一个有趣的问题!答案将取决于您使用的硬件的具体情况以及您拥有的C编译器

从C语言的角度来看,每个对象都有一个地址,但没有特定的规定机制来说明如何实际存储或访问该地址。这由编译器决定

假设您已经将数组声明为局部变量,然后编写类似于
array[137]
的代码,它访问数组的第137个元素。生成的程序如何知道如何查找数组?在大多数系统上,CPU有一个称为堆栈指针的专用寄存器,它跟踪用于当前函数的所有局部变量的内存位置。当编译器将C代码转换为实际的可执行文件时,它会维护一个内部表,将每个局部变量映射到远离堆栈指针指向的某个偏移量。例如,它可能会说这样的话:“因为64字节已经被这个函数中的其他局部变量用光了,所以我将把
array
64字节放在堆栈指针指向的地方。”然后,无论何时引用
array
,编译器都会生成该形式的机器指令“查找堆栈指针后面的64个字节以查找数组。”

现在,假设您编写了如下代码:

printf("%p\n", array); // Print address of array
编译器如何为此生成代码?在内部,它知道数组超过堆栈指针64字节,因此它可能会生成“将64添加到堆栈指针,然后将其作为参数传递给
printf
”形式的代码

因此,从这个意义上说,您的问题的答案可能类似于“硬件存储一个称为堆栈指针的指针,生成的代码以一种方式编写,即获取该堆栈指针,然后向其添加一些值,以到达数组所在的内存点。”

当然,这里有一系列的注意事项。例如,一些系统同时具有堆栈指针和帧指针。解释器使用完全不同的策略并保持内部数据结构跟踪所有内容。如果数组存储在全局范围内,则使用完全不同的机制


这是一个有趣的问题!答案将取决于您使用的硬件的具体情况以及您拥有的C编译器

从C语言的角度来看,每个对象都有一个地址,但没有特定的指定机制来解释如何实际存储或访问该地址。这由编译器决定

假设您已经将数组声明为局部变量,然后编写类似于
array[137]的代码
,它访问数组的第137个元素。生成的程序如何知道如何找到数组?在大多数系统上,CPU有一个称为堆栈指针的专用寄存器,用于跟踪当前函数的所有局部变量所使用的内存位置。当编译器将C代码转换为实际值时可执行文件,它维护一个内部表,将每个局部变量映射到远离堆栈指针指向的某个偏移量。例如,它可能会这样说:“因为此函数中的其他局部变量已经使用了64个字节,所以我要将
数组
64个字节放置在堆栈指针指向的位置。然后,每当您引用数组时,编译器都会生成“查找堆栈指针后64个字节以查找数组”形式的机器指令

现在,假设您编写了如下代码:

printf("%p\n", array); // Print address of array
编译器如何为此生成代码?在内部,它知道数组超过堆栈指针64字节,因此它可能会生成“将64添加到堆栈指针,然后将其作为参数传递给
printf
”形式的代码

因此,从这个意义上说,您的问题的答案可能类似于“硬件存储一个称为堆栈指针的指针,生成的代码以一种采用该堆栈指针的方式编写