C/C++ 指针笔记

下面这些内容存在很高的总结性,可能一句话就需要很大的篇幅和例子进行说明。所以,如果你有疑问可以自己写代码测试(个人认为自己写代码测试时最好的学习方法),当然也可以在下面评论交流。


1指针是什么?指针变量是什么?

指针是内存单元之间的一种指向关系,也是CPU寻址方式的一种体现。CPU在寻址时,如果直接给出存储单元A的首地址,这种寻址方式叫做直接寻址,而如果给出的不是存储单元A的首地址,而是先把存储单元A的首地址存放在另一个存储单元B中,然后给出B的地址,然后依靠B的地址去访问A的内容,这种寻址方式就叫做间接寻址。此时B保存A的地址,我们说B指向A,也就是B中保存的是指向A的指针。当然B中的内容是A的地址。但地址和指针不可以混为一谈。

指针变量是一个变量,它保存的是地址,它体现出的是两个存储空间的指向关系。

2& * 的说明:

首先这是两个编译器来识别的运算符。

& 代表变量的地址,首先变量的地址在每一次运行时可能不是固定的,但是它相关于一个基础地址的偏移量肯定都是一样的,这个跟程序的载入有关。

* 表示的是取该地址中的值。*p 就表示以p的内容为地址的存储空间的内容。即 p指向的空间的内容。

3指针和数组的一致性

p = a; a[5]  == *(p+5),需要多说一句的是,p+5 表示的首地址按数学方法计算的话是p+5*sizeof(*p)

4、如果a 是数组名,那么编译器认为a&a是同样的。

5编译器关于int a[3][4]的解释,其实真正的是给定a[1][2](a[i][j]) 的寻址方式,a 是一个int ** 类型的变量,&a[1][2] = a + 1*sizeof(*a) + 2*sizeof(**a) sizeof(*a) = 4* sizeof(**a), 同样的,int (*p)[4];本质上也就是包含两个信息,p int ** 类型, p+1 = p + 4*sizeof(int).用下标和*表示数组元素的关系,a[1][2] = *(*(p+1)+2)

6指针可以进行赋值、比较、加减常数运算。

7、不知道为什么,很多人都喜欢对那几个字符串处理函数翻来覆去的搞,虽然效率上会有轻微的提升(用了寄存器寻址间接寻址),但是从代码的可读性上来说,却并不算是什么好事。指针可以提高执行效率,但是代码的可读性变差,指针是面向内存的根本,也是C语言的灵魂,但是个人感觉还是只在必要的时候使用。

8函数指针:指向一个函数的入口地址。定义一个函数指针: 返回类型    (*p)(参数);      eg int (*p) (int); p(1)(*p)(1)

很多封装好的语言(javaC#)用这种方式来处理事件,MFC中也大量使用。基本的处理方法就是把一个函数的指针作为参数传递到其他的函数中去。当然这种方法对作为参数的函数有严格的格式限制。通常如果一个带有参数的函数名作为参数传递时,可以把它的函数名和参数分别作为子函数的参数。eg void fun(int a){} ==> int fun1(int a, void(*p)()){};  fun1(a,fun);

9、区分下面两个式子中指针p的含义:

int (*p)[4] int* p[4],这两个式子中,如果和数组做比较的话,第一个相当于intp[][4],第二个则是int p[4][](当然这样写是不符合语法的),  p都相当于二级指针,但编译器对其类型的解释是:下标的结合性优于*[]符号可以提前,第一个*p的类型是int[4] 类型,p则是int[4]* 类型,第二个p int*[4]类型,如果这样说仍不太容易理解的话,我们就看编译器是如何使用他们计算的吧,对于第一个p+1 == p + 4*sizeof(int),*p +1 == *p +sizeof(int), 对于第二个,p+1 == p + sizeof(int *),*p + 1 == p + sizeof(int)   需要再次说明的是,这些定义的方式是由编译器所要求,不同的定义,编译器就有不同的解释和使用方式,但指针所代表的含义在本质上是一致的,我们可以用强转的方式去随意使用他们,当然这样做也有不好的地方。

10、从上面的理解中,我们再看一个多级指针如何理解

 int **p; 它相当于int p[][] ,p + 1 要如何解释呢? p int ** 类型 p + sizeof(int*)

对于以上的写法和概念不应该去死记硬背,而是要理解他们的意义,做到灵活使用就可以了。

int(*p)[4]数组指针,指向一个长度为4的数组的指针,既然是指针,那么它占用的内存空间的长度就只有4个字节(32位机)

int*p[4] 指针数组,定义一个数组,数组的元素为指针,占用的内存空间数就是length * 4,就是一个常变量。

int** p 指向指针的指针,当然它就是一个指针,占4个字节。

在给他们分配完内存空间后,剩下的其实就是编译器来处理的内容了,规范他们的使用方式。即按下标(数组),或指针加减的方式。在对其赋值时,是否具有一致的寻址算法(即加1表示的意义是否一致)

使用指针的技巧:保持指针级数相同即可,也就是熟练区分一级指针,二级指针,数组指针等。

11、执行程序时,给定参数的方法。

首先在main函数中,要添加两个参数(int argc,char* argv[])

执行程序时,给定命令参数,argc会自动保存命令中字符串的个数,命令本身也算一个,argv[] 数组,则保存各个参数字符串的地址。注意argv 是指针数组。

 

 

虽然从内存的角度解释指针的含义已经简单了很多,但是由于编译器对指针的语法限制过于复杂,想要熟练使用,我还需要多加练习。

发布了41 篇原创文章 · 获赞 3 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章