éta*_*ogy 3 c arrays gcc pointers
一个阵列是特别不一个指针.可以肯定的是,两个左值似乎都包含(1维)虚拟内存中某个位置的(1维)坐标.但请考虑这个例子.
#include <stdlib.h>
#include <stdio.h>
int main(){
char buffer0[4096];
char* buffer1 = malloc(4096);
printf("lvalue %16p sizeof %lu\n", (void *) buffer0, sizeof(buffer0));
printf("lvalue %16p sizeof %lu\n", (void *) buffer1, sizeof(buffer1));
// Example output: lvalue 0x7ffcb70e8620 sizeof 4096
// Example output: lvalue 0x7a4420 sizeof 8
}
Run Code Online (Sandbox Code Playgroud)
想到的实际差异是:
malloc() 必须知道指针有多大,知道free()只给指针多少......!)free()它们); 指针必须手动释放(如果它们拥有非常重要的内存量,即通过malloc())总的来说,数组似乎比指针更聪明(但功能更少)(他们知道它们有多大,它们有多少元素,并且它们具有自动内存管理).
问题
数组如何“知道”它们有多大?这是如何实施的?
数组不知道它们有多大——没有与数组关联的元数据来指示大小(或类型,或其他任何东西)。 在翻译期间,编译器知道数组有多大,并且sizeof在那个时候处理依赖于该知识的任何事情(指针算术、运算等)。一旦生成机器代码,数组就只是一块愚蠢的内存 - 没有办法在运行时通过查看数组对象本身来确定数组有多大(除了可变修改的类型,如可变长度数组,sizeof运算是计算的在翻译期间,而不是运行时)。
一般而言,C语言中数组是如何实现的?(是编译器这样做,还是内核这样做?
数组只不过是相同类型对象的连续序列。对于声明
T arr[N]; // for any type T
Run Code Online (Sandbox Code Playgroud)
你得到
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
| | arr[2]
+---+
...
+---+
| | arr[N-1]
+---+
Run Code Online (Sandbox Code Playgroud)
没有arr独立于数组元素本身的对象,也没有为大小、起始地址、类型或其他任何内容留出任何元数据。
下标操作arr[i]被定义为*(arr + i)给定阵列的起始地址,偏移-i元件(而不是字节!从该地址和取消引用的结果)。
您是正确的,数组不是指针 - 但是,除非它是sizeof或 一元运算&符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则数组类型的表达式将被转换(“衰减”)到指针类型的表达式,表达式的值将是数组第一个元素的地址(同样,这都是在翻译期间完成的,而不是在运行时完成)。
因此,当您编写类似 时x = arr[i];,编译器会将表达式转换arr为指针值,因此下标操作有效。
与此相反,当你写ap = &arr;,编译器并没有转换arr为指针类型。结果仍然与第一个元素的地址相同,但类型不同 - 而不是T *,类型是T (*)[N],或“指向 N 元素数组的指针T”。
数组如何"知道"它们有多大?这是如何实现的?
编译器知道这一点.
一般来说,如何用C语言实现数组?(编译器是这样做的,还是内核?
编译器.
================================================== ========================
您需要关注的一点是,数组是一种类型.它是派生类型.
引用C11,章节§6.2.5/ P20,
数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型.只要指定了数组类型,元素类型就应该是完整的.数组类型的特征在于它们的元素类型和数组中的元素数.[...]
所以,本质上,就像编译器知道有关大小的任何其他类型的,它知道数组类型的大小,也.
总大小是根据元素类型的大小乘以该数组中元素的数量计算的.
数组的类型包含其大小(作为编译时常量)及其成员类型.因此,由于编译器知道所有变量的类型,它只能计算sizeof(the_array)为sizeof(array_type.element_type) * array_type.element_count.
在内存分配等方面,它们只是像任何其他变量一样对待:
如果声明数组类型的自动变量,则会将sizeof(the_array_type)字节数添加到堆栈帧的大小.因此,当输入函数时,堆栈指针增加足以存储数组的内容,并且当函数退出时,它将减少相同的量.
如果声明具有静态持续时间的变量,sizeof(the_array_type)则将在二进制数据段中保留.
同样,这与处理任何类型的所有变量的方式相同.重要的是,数组只包含其元素,因此其大小是其内容的大小,而指针仅指向其元素,其大小完全独立于其指向的内容.
当用作外部的r表达式时sizeof,数组的名称只是编译为其地址(并键入为指针).
编译器是这样做的,还是内核?
所有这些都是由编译器完成的.
| 归档时间: |
|
| 查看次数: |
549 次 |
| 最近记录: |