指针与数组

> 一级指针 

c语言在对程序进行编译时,系统会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。

  

指针就是变量的地址,指针变量其实也是一个变量,他跟别的变量并没有太大的区别,别的变量可能是存放值,而指针变量是专门存放地址的变量。

指针变量的简单例子:


 

其实int *p 对这个※,人们都有过这样的困惑,这颗※到底跟谁结合。其实在高质量的C C++编程这本书中有一种说法:是把*跟后面的变量放在一起。


当我们用int* p时,固然p的类型很明了,但是当出现int*   x,y时候很容易y被人们误解成是指针变量。所以高质量的C C++编程中将*与变量名结合定为规则。


> 二级指针(指针的指针) 

               同时,指针变量也是变量,是变量就有地址,那指针变量的地址就存放在二级指针中。 


对于二级指针的运算有解引用,譬如*pp 找到的就是p这块空间。


对上图中int **pp = &p的分析:

首先*操作符具有从右向左的结合性,所以这个表达式相当于*(*pp)。我们必须从里向外逐层求值。*pp访问pp所指向的位置,我们知道这是变量p,第二个间接访问操作符从这个位置所指向的地址,也就是变量i。

Pay attention:对于一些表达式的剖析

*cp+1;

注意:此表达式的结果不能作为左值。指针加法运算的结果是一个右值。(因为*cp访问到的是字符‘a’,再加一访问到的是字    符‘b’,字符‘b’当然不能作为左值)

*(cp+1

注意:(先1+cp中所存储的内容相加,若没有间接访问操作符,这个表达式将不是一个合  法的左值,然而间接访问操作符跟随指针访问一个特定的位置。这样*(cp+1)就能作为左值使用,尽管cp+1本身不      是左值。间接访问操作符是极少数几个其结果为左值的操作符之一)

++cp和cp++

注意:这两个表达式的值都不是合法的左值。


> 一维数组 (以一种相当优雅的方式把一些完全不同的概念联系在一起)

                                                                   一组有序数据的集合                                                                             

首先,数组名的值是一个指针常量,他指向数组第一个元素的地址。注意在两种条件下,数组名并不用指针常量来表示,---就是当数组名作为sizeof操作符或者单目操作符&的操作数时。sizeof返回指向返回整个数组的长度,而不是指向数组的指针的长度。取一个数组名的地址所产生的是一个指向数组的指针,而不是指向某个指针常量的指针。

注意不能使用赋值符把一个数组的所有元素复制到另一个数组。必须使用一个循环,每次复制一个元素。

  a = c;c被声明为一个指针变量,这条语句看上去像是执行某种形式的指针赋值,把c的值复制给a。但是这个赋值是非法的;

住:在此表达式中,a的值是一个常量,不能被修改。数组名不能作为左值。

> 二维数组 

又叫:“矩阵”数组的有两个维数                                       

在C语言中,二维数组中元素排列顺序是按行存放的,即在内存中先顺序存放第一行的元素,接着再存放第二行的元素。

 譬如这种的存储方式,是按行存储的(ps:每个空间大小应该相同~)


二维数组在c语言中可以被看做是一种特殊的一维数组:它的元素又是一个一维数组。

这个arr【3】【4】其实有两种解释。在某些上下文环境中,说他是3行4列,或者说他是4行3列答案都对。

 根据下标把数据存放在数组中并在以后根据下标查找数组中的值,那么不管将第一行解释为行或者列都不会有什么区别。

其实如果你把第一个下标解释为行,把第二个下标解释为列,那么当你按照存储顺序逐个访问数组元素时,你所获得的元素是按行排列的,另一方面,把第一个当做列,那么按照前面顺序访问数组元素时,你得到的元素是按列排序的。

> 指针和数组的关系 

指针和数组并不是相等的。

arr与b 都具有指针值,他们都可以进行间接访问操作和下标引用操作。但是他们还具有相当大的差异。

声明一个数组的时候,编译器将根据声明所指定的元素数量为数组保留内存空间,然后再创建数组名,他的值是一个常量,指向这段空间的起始位置。声明一个指针变量,编译器只为指针本身保留内存空间,他并不为任何整型值分配内存空间。而且指针变量并未被初始化为指向任何现有的呢存空间,如果他是一个自动变量,他甚至根本不会被初始化。

因此:*a是完全合法的。*b不是合法的

数组名是指针常量。  b++可以通过编译,a++确不行    a的值是一个常量。

> 指针数组 

一个数组,若其元素均为指针类型数据,称为指针数组

指针数组,其本质是一个数组,只不过每个数组中存放的是整形元素的地址。

ps:           

> 数组指针

直线数组的指针

  p是一个指向拥有10哥整形元素的数组的指针。当你把p与一个整数相加时,该数组的值首先根据10个整型值的长度进行调整,然后 再执行加法。故有此指针就可以实现一行一行的在arr数组中移动。


PAY:  尽量避免 int (*p)[ ] = arr;这种写法,p依然是一个指向整形数组的指针,但是数组的长度却不见了。当某个整数与这种类型的指针执行指针运算时,他的值将根据数组的长度进行调整(即:与0相乘)。 有的编译器可以捕捉到这种错误,而有的编译器却不行。


数组指针分析:当我们对int (*p)【10】,进行间接访问操作时,我们得到的是一个数组,对该数组进行下标引用操作得到的又是一个整数的值,所以p是一个指向整形数组 的指针)


> 函数指针 

        (转换表)&&(作为参数传递给另一个函数)   




函数加取地址符与本身输出的(地址)结果一样。     fun();  *fun()与(*fun)()  第一个结合性()的结合性更高。 第二种写法可以。


指针函数与函数指针:  1: void *p (int ,char );  2: void (*p) (int ,char);

返回值是void * 的函数 函数的指针(函数的指针变量q)

void *fun (char *str, int a)           的函数指针形式  void* (*pfun) (char*,int)

分析: (* (void(*)())0)()

    先把0强制类型转换 参数类型为空 返回值为void 的函数指针 ,再对其进行解引用 再传参 

             即:调用0地址处的函数


void (*signal)(int,void (*)(int)))(int);

signal是一个函数 参数是一个int 的参数,和一个函数指针 他的返回类型又是一个函数指针

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值