zoukankan      html  css  js  c++  java
  • <C和指针---读书笔记8>

    数组 , 数组是C语言的一种数据类型。 我们先从一维数组讲起.

    声明和初始化

    type  数组名[n]  : 声明了一个数组,它由n个元素组成,且这n个元素均是 type类型。

    编译器进行初始化时,会为其分配 n个type型存储空间. 如int a[4];

    在声明时, 编译器需要为其分配空间,所以需要知道数组的长度信息,类型信息。

    int b[] ; 就是非法的。 int b[] = {1,2,3,4};是允许的。原则就是能提供长度信息与否。

    数组名的纠纷

    我们知道a[0]表示元素0、a[1]表示元素1. 那单字母a表示什么?按道理应该是整个数组的简写。

    但实际上并非如此简单。其实,在编译器进行编译时,会有一个记录表格: 它记录了代号---地址的关系.

    显然,如果仅仅是int x ; 它记录 x --- addr_880 . 以后访问x,都是去访问的880地址。

    指针变量也是如此, int *p ,它也会记录 p ---- addr_990 .

    但到了数组名这里就不一样了,因为数组名不是一个变量,它不拥有自己的存储领地, 但编译器仍然记录了下来对应关系.

    它记录的是:   数组名 ------ 首个元素的地址 . 

    我们已经知道了记录的关系了,那在编译过程中,遇到数组名, 编译器将会做什么操作?

    下标的引用

    在普通的操作中,我们接触到的b[2]。编译器遇到这种形式: 都会先把它们翻译成间接操作*(b+2) .

    为什么要翻译成间接操作呢?  因为它本质上想表达的意思是:  访问数组b的第三个元素。

    因为编译器没有记录各个不同元素的地址信息,只记录了首元素的地址信息,并对标给了数组名b,所以要把这里作为突破口.

    *(b+2)  = *(首地址+偏移)。 很明显,编译器在执行这个b+2中,如果只是简简单单的+2,就没有任何的物理意义了。

    编译器执行的将是:  b + 2* sizeof (int),从而能顺利的访问 b[2]元素。

    指针的介入

    我们知道,指针变量,可以指向任意内容.如果我们把指针指向了 数组的第一个元素.

    int arry[10] ;

    int *ap = arry;  (把地址存入ap变量内)  

    int *ap = arry +2  (把"地址+2 * sizeof (int) "存入ap变量内,即把元素2的地址存入指针变量内)

    这时候,对指针进行间接访问, 均是访问的元素2.   

    ap

    指针常量,指向元素2   (编号从0开始)

    *ap

    左值:存入元素2内;  右值,获取元素2内的值

    Ap[0]

    从字面上,我们觉得这是错的,因为ap是个指针啊,它又不是数组,你怎么对它进行这种操作呢?

    其实:我们记得下标引用时 间接访问的一种伪装。所以这个依旧是间接访问的一种 *(arry + 0) = *ap

    用作左值:存入元素2内;右值,获取元素2内的值

    Ap+6

    Ap是一个指针,指针的加法 = + 6*sizeof(int)

    所以是指向 元素8

    *ap+6

    arry[2]的内容+6

    *(ap+6)

    用作左值:存入元素8内;右值,获取元素8内的值

    ap[6]

    同理, ap[6] = *(arry + 6) ,跟上面一样

    &ap

    显然是获取指针变量的地址。

    Ap[-1]

    Ap[-1] = *(arry -1 ) ,

    用作左值:存入元素1内;右值,获取元素1内的值

    Ap[9]

    Ap[9] = *(arry +9)  超出了范围。是很冒风险的事

    2[aary]

    依旧是合法的,很奇怪是吧,

    2[arry] = *(2+arry) = *(arry+2)

    指针表示还是b[n]表示

    我们可以通过定义一个指针,并让它指向数组的首地址,通过加减指针变量,完成访问。 也可以通过b[n]来访问数组元素。

    各有利弊,b[n]看起来易读、易于维护。指针形式效率 ≥ b[n]形式

    数组用作函数参数

    在子函数定义时,我们时常会把一个数组当成参数的一份子. 

    在子函数body中,我们通常也会对其进行访问操作,使用的无非是指针,或者b[n]形式。 最终编译器都将这些操作

    转换成了*(b+2)  = *(首地址+偏移) 操作. 显然我们只要知道 首地址信息就够了. 即子函数定义时,我们的参数列表,

    只要指定一个数组名就可以了,不必指定长度了. 

    在函数调用前的 函数原型声明时, 传进来的参数也是要是一个数组的首地址就够了,你可以用数组名的方式,也可以用指针的方式.

     

     

  • 相关阅读:
    Pale Moon 15.1 发布,苍月浏览器
    开源云端代码编辑器 ACE 1.0 正式发布
    Jailer 4.0.14 发布,智能数据提取工具
    Bitcoin 0.7.0 发布, P2P网络的匿名数字货币
    Pike 7.8.700 发布,脚本编程语言
    PhoneGap 2.1.0 正式版发布
    DHTMLX Touch 1.2 发布,移动 JS 框架
    abcm2ps 6.6.20/7.1.0 发布
    Little CMS 2.4 发布,色彩管理引擎
    Linux静态库和动态库
  • 原文地址:https://www.cnblogs.com/mokang0421/p/7482548.html
Copyright © 2011-2022 走看看