指针与数组


珊瑚

一、指针与地址

  • 内存的组织方式——地址

      内存以字节为单位,可操纵单个或一组字节的存储空间进行存储数据。对内存的所有字节空间连续编址或编号,这就是内存地址。


  • 指针

      不同数据类型可操纵的连续字节内存空间有所不同,如字符 char 类型可操纵一个字节,可存储 256 个数二进制数。指针不能存储表达式、常量和 register 类型的变量的,只能储存变量和数组元素的地址。


  • 指针的定义声明

      *号最好紧靠标识符的左边,不易出错些,定义形式如下:

    类型 *标识符;

    指针类型与其值的类型一致。
  • 指针如何获取对象地址

      一元运算符“&”,可用于取对象的地址。下列赋值语句取对象地址放入指针中:

    指针变量 = &要获取地址的对象;

  • 指针如何使用其值

      一元运算符 * 是间接寻址或间接引用运算符。通过间接寻址符访问指针的值的值,地址指向的数据。

    *指针变量

    这样就可访问指针的值,即地址的值了。
  • 指针也是变量

      同类型指针之间不必通过间接寻址符交换值(值是其他对象的地址),空类型指针比较特殊。



二、指针与函数参数

  • 函数的值传递

      调用函数向被调用函数的参数传递数据是复制一个值副本,参数变量装的是副本值,不会改变调用函数中对象的值,但若是复制的是对象的地址呢?情况有所不同,地址是唯一的,寻址就可间接的访问调用函数的对象了。


  • 函数指针参数

      定义形式如下:

    类型 函数名 (类型 *对象名,类型 *对象名,…)


三、指针与数组

  • 什么是数组

      数组是一组有限大小的连续内存空间上的同类型数据有序集合。下标从0开始递增的,访问数组相应下标的元素。

    类型 数组名[元素个数下标];

  • 数组与指针

      数组由一个或多个同类型并且在内存说紧邻有序排放的数据集合,使用0下标开始代表有限个数组元素。数组名存储元素0的地址。地址可进行算术运算。

    指针 = 数组名[下标]或数组名,(指针 加减 指向第几个元素)——地址,(指针 加减 指向第几个元素)——寻址访问。反之指针也可像数组一样。

    注意:数组不是变量,不可储存其他地址,不可自加和自减地址,而这些指针可以。数组名a,(a + i)只是对地址加i,并没有改变数组a的地址。


    特别点:当参数声明为数组时,传给形参的不管数组名代表首地址,还是用取地址符取元素地址,数组作为函数参数时,参数实际上最终是指针,指针用法和数组用法都可用。就是退化为指针了,所以一般使用指针作为数组的形参。

四、地址算术运算

  • 指针变量和数组的地址

      地址的最小单位是字节。不同类型的数据对象可操控的字节数量,即某种数据类型的对象的长度有所不同,如一个字符型对象可操纵长度是一个字节,如超过一个字节,以对象的首地址为它的地址。

    指针——指针是一个储存地址的变量,初始化的地址一般是本程序已知或0的地址,C语言保证0地址永远不是有效地址,0地址可与整数0相互转换,为清楚知道是指针,所以定义宏NULL表示地址0。
    数组——形式如 “数组标识符[从0开始的N个下标]”,代表定义了地址连续的N个同类型对象,标识符加下标表示数组的各个元素对象,使用取地址符&可获得各个元素地址;数组名不加下标表示元素下标为0的地址。

  • 地址的运算
    • 指针的算术运算的一致性

        指针变量加1,指向的地址会加到类型的整数倍,加N,加到该类型整数倍N个后的地址。所有的指针运算都会自动考虑类型的长度。


    • 有效的指针运算

        同类型指针之间的赋值运算;指针和整数之间的加减法运算;指向相同数组的指针之间的减法运算和比较运算;将指针赋值为0或指针与0之间的比较运算。


    • 无效或非法的指针运算

        除了有效运算外,其他都是非法或无效的。两个指针之间进行的加法、乘法、除法、移位运算或屏蔽运算;不同类型的两个指针,不经强制转换是不能进行赋值运算(两指针之一是void *类型除外)。


五、字符指针

  • 字符串常量

      字符串常量是一个字符数组,如,“I am a string"。字符串内部表示,是以空字符’\0’结尾,所以实际字符数要多一个。


  • 字符指针

      字符串常量赋值给字符指针,只是赋值字符数组的第一个元素地址(字符串常量第一个字符地址)。字符指针还可是字符串的下一个对象地址或其他字符对象地址。引用时可根据结尾符’\0’大做文章。


六、指针数组与指针的指针

  • 指针的指针

      指针也是变量,所以本身分配了地址空间。指针的指针,是一个变量,存的是另一个指针变量的地址。

    类型 **指针名;

    单目运算符*从右到左匹配,*指针名定义一个指针,后面表示储存类型是某类型的*指针。
  • 指针数组

      指针数组是某种类型的指针构成的数组,可存放该类型的指针元素。

    数组的元素是该指针的地址,与指针的指针一样的道理,只不过存指针的是一个数组。

七、多维数组

  多维数组的元素一维数组构成的,一个数组是由一层数组构成,就是二维数组、由二层数组构成就是三维数组,依次类推,一般常用一维数组和二维数组。
  • 声明和初始化

      一般来说,数组的第一维(下标)的大小可以不指定,其他维都必须确定大小。初始化跟一维数组一样,只不过元素又是数组,所以元素初始化用子列表,就是把元素换成一对花括号。

    例子:类型&bnsp;数组名[][确定大小] = {
     {,},
     {,},
      ,

      ,
     {,}
    }

  • 多维数组作为函数参数

      作为函数参数,可以写成三种形式,下面用二维数组举例:

    函数返回类型 函数名(参数类型 数组名[常量][常量]){…}
    函数返回类型 函数名(参数类型 数组名[][常量]) {…}
    函数返回类型 函数名(参数类型 (*数组名)[常量]){…}

    第三种,是声明为指向一维数组的指针,数组在某些方面互转是可以滴!这叫数组指针。

八、指针数组的初始化

  指针数组的元素是指针,所以初始化列表值是一些同类型指针,如用储存字符串的的指针数组举例:
char *name[] = {
"zifu",
"zifu1","zifu2",
...,
"zifumo"
};

元素是字符指针,所以指针数组实际存的是字符数组的首字符地址。

九、指针与多维数组

  搞清楚指针与多维数组的关系,是很有必要的。如指针数组里面的指针与二维数组的关系与区别。
二维数组的第二维大小必须指定,且分配了同类型元素指定的数量大小储存空间,是固定的。一维指针数组,没有默认数组大小,而是通过静态初始化和代码中显式初始化,他的维度可同二维数组的二维一样,等同二维数组,但也可是随意的,比如存放字符指针的字符指针数组,元素长度是随意的。

如:char zifu[][5] = {
"hello",
"world" };
char *pzifu[] = {
"hello.",
"hello,world" }

总结:指针数组可以模拟二维数组,不是真正意义上的二维数组,但指针数组的可变元素长度,是像二维数组不能模拟的。

十、命令行参数

  在支持C语言的环境中,可以在程序开始时调用程序主函数main(int argc, char *argv[])。第一个参数argc是操作系统用于统计字符指针数组的字符串个数的。第二个参数argv字符指针数组用于输入参数的,数组的首元素,C语言约定为程序名字的字符串,所以argc参数值必须至少为1,字符串之间使用空格隔开,形如argv[argc]的值必须为空指针。
命令行中:程序名字字符串 其他字符串 ...

十一、指向函数的指针

  • 空类型指针——void*

      没有指定指针类型的指针,仅仅是一个地址。任何类型的指针都可强制转换为空类型指针,也可把空类型指针转换所需的类型。空类型指针不可地址运算,因为没有类型,也不可寻址,没有类型数据无意义。


  • 指向函数的指针

      函数虽说不是变量,但和数组名一样,储存了一个函数的首地址,函数名相当于数组名常量指针。声明一个指向函数的指针变量,可用最函数调用和把函数作为函数参数。一般形式如下:



    指针类型 (*函数指针名)(void *,void *);

十二、复杂的声明

     

特别内容

——数组,数组名是常量指针,表示数组元素首地址。获取带以下标元素的地址,使用&取地址符。
——数组与指针,数组转指针,获取数组名的值,就可通过地址运算遍历数组了。
——指针数组,是可存储某类型指针的数组,它是数组。数组名依然是代表元素首地址,即首个元素指针的地址。数组名加下标,表示对应的指针的值,也就是指针的内容。获取带下标的元素指针的地址使用&。
——指针数组作为参数,实际上数组会退化成指针形式处理,指针数组里储存的是指针,理所当然退化成二级指针,也就是指针的指针。二级指针会得到指针数组的元素首地址。其他元素指针,使用遵循地址运算规则就可。

C语言运算符优先级与求值次序

运算符优先级结合性
() [ ] -> .从左至右
! ~ ++ – + - * & (type) sizeof从右至左
* / %从左至右
+ -从左至右
<< >>从左至右
< <= > >=从左至右
== !=从左至右
&从左至右
^从左至右
|从左至右
&&从左至右
||从左至右
?:从右至左
= += -= *= /= %= &= ^= |= <<= >>=从右至左
,从左至右

注:结合性是运算符匹配操作数,同优先级一般从左至右计算表达式,有不同优先级运算符根据结合性再计算。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值