一、关于二维数组的学习。
1、测试过程
关于二维数组自己其实学的差不多了,但发现二维数组作为形参时自己理解的还不是很到位,特此写下来测试demo分析。
编译过程发现:
运行结果:
总体来分析:总体结果符合预期,就是用二重指针这个地方为什么会段错误?
2、汇编代码分析
分析如下:二维数组名本身还是一个指针,只不过是一个特殊类型的指针(数组指针),代表这个数组的首地址,我们定义参数为int array[3][5]或者int (*array)[5]时,会告诉编译器:这是一个数组指针,因此c标准规定取元素时必须**array而且跨度是一维数组的长度,但编译完以后的汇编代码可以看到只是取了一次地址(ptr),可以看到array = array.
对于一维数组,只有当数组名在表达式中使用时,编译器才会产生一个指针常量,形参会把指针常量赋给一个指针(顶层const)。而只有以下两种情况,才不被当做指针常量(来自c和指针P141),.
①、sizeof(数组名),返回的是数组长度,而不是指向数组的指针长度,编译时一般都会确定。
②、&数组名,产生一个指向数组的指针,而不是指向某一个指针常量的指针。
二、关于函数栈的学习。
验证csdn上的评论:形参也占用栈内存。
其实下面的图中右边的图是不正确的(2和4在上面),早期的CISC结构是栈密集型,参数的传递是通过调用者存储,具体可以参考汇编代码。其实后来的CISC也可以用寄存器传递参数(6个,参考CSAPP)。
三、虚拟内存。
在linux系统中,CPU不能按照物理地址访问存储空间,必须使用虚拟地址,所以就有“反向”地从物理地址出发找到一片虚拟空间并建立映射(设置页表),最经典的应用就是ioremap。至于DMA 区域为什么要分开,则由于DMA区域的特殊性1、外设要求物理地址不能过高,2、DMA要求物理页连续(因为DMA访问内存时没有经过mmu),3、DMA使用的页面是磁盘必须的,进行页面与盘区的交换。
页面可以分为物理内存页表和物理盘上页面,就算在VMA链表里面,也可能是没有建立页表映射。
四、feof。
- 判断是否EOF一般只适用于文本文件(特别是char读进FF),feof既可以用于二进制文件,也可以用于文本文件。
- 文件结束符一般都会有EOF.但fread不会读近来,只是把position后移。
- 文件到最后了每一次fgetc都会读进-1。