指针与数组知识点总结
2017-10-28 19:53
295 查看
本文基于flying_music博客,加入自己的一些理解,请周知
1.印子——指针为什么需要返回类型
我们用C语言写了这样的语句
[cpp] view
plain copy
int a;
a = 3;
编译器为了完成这两句代码,首先在编译过程中要创建一个符号表,样子大概如下图:
然后在运行过程中,编译器发现a=3这句代码时,会在符号表里找a对应的地址,然后把3放入对应的地址,即这里的0x1000。(A找B盖章,直接盖到了)
如果是*p=3会怎么做呢?首先,符号表变成了这个样子
在运行过程中,编译器遇到*p=3时,首先要从符号表中找到p的地址0x1004,然后取出0x1004中的内容,这里假设为0x2000,最后把3放到0x2000内存地址中,即*(0x1004)=3。
相比于利用普通变量,利用指针存取数据的过程中多了一部取地址的的过程。这也就是指针变量与普通变量最大的不同。
再来看一下指针加偏移量的引用方式,还以上面的指针p为例,让我们来看一下*(p+2)=3的实现过程。
首先,编译器从符号表中找到p然后,取出里面的内容0x2000,再根据其类型(int*),做一个运算,
0x2000+2×sizeof(int)=0x2008。所以编译器会把3放入0x2008这个内存地址。
整个过程可表示为*(*(0x1004)+2)=3。(A找B盖章,B讲你去C部门,找那谁盖章(偏移))
从这里也可以看出为什么指针必须有类型,因为在引用过程中要用到指针所指类型的长度。
来看一下,数组元素的引用是如何实现的,假设我们定义了一个数组,并对其元素进行了引用
[cpp] view
plain copy
int b[10];
b[4] = 3;
对应的符号表变成了这个样子
那b[4]=3如何完成呢?首先,找到符号b,然后发现其类型为int[](假想表达方式,C语言中不支持这样写),所以计算式变成了0x1008+4×sizeof(int)=0x1018,然后把3放入0x1018就可以了。用一个式子表达就是*(0x1008+4)=3。(A找B盖章,B讲你去我们部门,找那谁盖章(偏移))
从上面的寻址式子可以看出,普通变量、指针、数组三者对于编译器的区别。具体到数组,它即具有普通变量的直接性,即不用取两次地址里的内容而是取一次,同时又具有和指针相同的偏移量引用方式,即下标的实现实际是由指针加偏移量实现的。
为了表明上述事实(或者是为了提高C语言入门门槛),C语言对指针与数组的引用方式做了可以“交叉”使用的语法规定。就上面的例子来说,如果p指针指向数组b时,b[i]、*(b+i)、p[i]、*(p+i)都是对数组第i个元素的正确引用方式,这也给很多C语言学习者制造了“指针和数组一样”的错觉。
2.在函数形参中的表现
在向函数传递参数时,如果实参是一个一维数组,那用于接受的形参为对应的指针。也就是传递过去是数组的首地址而不是整个数组。这么做的原因主要是效率,这是无可争议的,但为了使用上的简便与通用,C语言接受两种形参的写法,即下面两种写法是相同的
[cpp] view
plain copy
int foo(int *a, int n);
int foo(int a[], int n);
甚至是
[cpp] view
plain copy
int foo(int a[20], int n);
在底层都是完全一样的形式。这简化了C语言的使用,但同时也增加了对其进一步理解的难度。
至于哪种写法好的争论,只要理解了,用哪种写法倒是不必强求。
指针形式表明了传参过程的实质,而数组形式表明了这个指针对应一个数组实参,甚至后面的数字可以提供数组长度的参考。
3.如何区分二者
数组和指针的关系如此微妙,那如何区分呢?
首先说为什么要区分,主要由两个方面的原因
一是C语言的主要战场还是偏向于底层的,使用者对这块儿一定要搞清楚,比如编译器,硬件系统等相关知识。 二是在特定的情况下,二者的表现的确不同,最常见的就是sizeof关键字的作用结果,另外还有取址操作符&的结果等情况。
至于如何区分,个人认为凡是要区分两个相关的概念,一定要将二者的作用区分清楚,即为什么要有这个东西。
数组和指针也是一样,指针是一类特殊的变量,主要用途是函数间的传址,用这种方式来改变实参内容。
而数组是用来实现线性表的结构,用于把同类对象集中在一起放置。
所以,如果下次有人问你数组和指针的区别,你首先第一句要说的就是二者根本没有联系,这么说并这么理解,对于弄清这两个家伙的关系是很有裨益的。
1.印子——指针为什么需要返回类型
我们用C语言写了这样的语句
[cpp] view
plain copy
int a;
a = 3;
编译器为了完成这两句代码,首先在编译过程中要创建一个符号表,样子大概如下图:
然后在运行过程中,编译器发现a=3这句代码时,会在符号表里找a对应的地址,然后把3放入对应的地址,即这里的0x1000。(A找B盖章,直接盖到了)
如果是*p=3会怎么做呢?首先,符号表变成了这个样子
在运行过程中,编译器遇到*p=3时,首先要从符号表中找到p的地址0x1004,然后取出0x1004中的内容,这里假设为0x2000,最后把3放到0x2000内存地址中,即*(0x1004)=3。
相比于利用普通变量,利用指针存取数据的过程中多了一部取地址的的过程。这也就是指针变量与普通变量最大的不同。
再来看一下指针加偏移量的引用方式,还以上面的指针p为例,让我们来看一下*(p+2)=3的实现过程。
首先,编译器从符号表中找到p然后,取出里面的内容0x2000,再根据其类型(int*),做一个运算,
0x2000+2×sizeof(int)=0x2008。所以编译器会把3放入0x2008这个内存地址。
整个过程可表示为*(*(0x1004)+2)=3。(A找B盖章,B讲你去C部门,找那谁盖章(偏移))
从这里也可以看出为什么指针必须有类型,因为在引用过程中要用到指针所指类型的长度。
来看一下,数组元素的引用是如何实现的,假设我们定义了一个数组,并对其元素进行了引用
[cpp] view
plain copy
int b[10];
b[4] = 3;
对应的符号表变成了这个样子
那b[4]=3如何完成呢?首先,找到符号b,然后发现其类型为int[](假想表达方式,C语言中不支持这样写),所以计算式变成了0x1008+4×sizeof(int)=0x1018,然后把3放入0x1018就可以了。用一个式子表达就是*(0x1008+4)=3。(A找B盖章,B讲你去我们部门,找那谁盖章(偏移))
从上面的寻址式子可以看出,普通变量、指针、数组三者对于编译器的区别。具体到数组,它即具有普通变量的直接性,即不用取两次地址里的内容而是取一次,同时又具有和指针相同的偏移量引用方式,即下标的实现实际是由指针加偏移量实现的。
为了表明上述事实(或者是为了提高C语言入门门槛),C语言对指针与数组的引用方式做了可以“交叉”使用的语法规定。就上面的例子来说,如果p指针指向数组b时,b[i]、*(b+i)、p[i]、*(p+i)都是对数组第i个元素的正确引用方式,这也给很多C语言学习者制造了“指针和数组一样”的错觉。
2.在函数形参中的表现
在向函数传递参数时,如果实参是一个一维数组,那用于接受的形参为对应的指针。也就是传递过去是数组的首地址而不是整个数组。这么做的原因主要是效率,这是无可争议的,但为了使用上的简便与通用,C语言接受两种形参的写法,即下面两种写法是相同的
[cpp] view
plain copy
int foo(int *a, int n);
int foo(int a[], int n);
甚至是
[cpp] view
plain copy
int foo(int a[20], int n);
在底层都是完全一样的形式。这简化了C语言的使用,但同时也增加了对其进一步理解的难度。
至于哪种写法好的争论,只要理解了,用哪种写法倒是不必强求。
指针形式表明了传参过程的实质,而数组形式表明了这个指针对应一个数组实参,甚至后面的数字可以提供数组长度的参考。
3.如何区分二者
数组和指针的关系如此微妙,那如何区分呢?
首先说为什么要区分,主要由两个方面的原因
一是C语言的主要战场还是偏向于底层的,使用者对这块儿一定要搞清楚,比如编译器,硬件系统等相关知识。 二是在特定的情况下,二者的表现的确不同,最常见的就是sizeof关键字的作用结果,另外还有取址操作符&的结果等情况。
至于如何区分,个人认为凡是要区分两个相关的概念,一定要将二者的作用区分清楚,即为什么要有这个东西。
数组和指针也是一样,指针是一类特殊的变量,主要用途是函数间的传址,用这种方式来改变实参内容。
而数组是用来实现线性表的结构,用于把同类对象集中在一起放置。
所以,如果下次有人问你数组和指针的区别,你首先第一句要说的就是二者根本没有联系,这么说并这么理解,对于弄清这两个家伙的关系是很有裨益的。
相关文章推荐
- C语言 总结数组指针相关知识点
- C++的数组、结构体、指针三种复合类型知识点小总结
- 数组指针与指针数组的知识点总结
- 读陈浩的《C语言结构体里的成员数组和指针》总结,零长度数组
- 字符数组,字符指针,sizeof的总结
- 读陈浩的《C语言结构体里的成员数组和指针》总结,零长度数组
- [转]字符数组,字符指针,Sizeof总结
- 2016年12月6日学习总结----指针与数组的区别
- C 总结——指针和数组是不同的两种东西
- 第十章 数组和指针(复习题总结)总结 140521 22 23
- C中关于一位数组与指针和二维数组与指针的一点总结
- 数组和指针的区别?总结
- C语言数组与指针学习总结
- 堆和栈的区别&字符数组,字符指针,sizeof的总结(转)
- 字符数组,字符指针,Sizeof总结
- 字符 数组 ,字符 指针 ,Sizeof总结
- 内存的堆分配和栈分配 & 字符数组,字符指针,Sizeof总结
- C++数组常记知识点以及指针对于数组的操作
- <C语言>数组与指针详细知识点(全)
- C/C++的一些关于字符数组和指针的小总结