当前位置:首页 > 单片机 > 单片机
[导读] 终于说到了指针。指针是C语言的精华部分,如果没有指针,c语言对底层的许多操作将无法完成。也是因为指针的存在,使得c语言看起来并不那么高级,因为指针操作的对象的是内存地址,想要熟练地进行指针操

终于说到了指针。指针是C语言的精华部分,如果没有指针,c语言对底层的许多操作将无法完成。也是因为指针的存在,使得c语言看起来并不那么高级,因为指针操作的对象的是内存地址,想要熟练地进行指针操作,必须考虑到内存等偏硬件方面的东西。当然,也不需要了解过多。但是,数据结构这一关还是要过的。我对数据结构方面了解尚浅,就不多说了。数组与指针的关系如此复杂,让我不得不照着书来写这一篇笔记了。

一、数组不等于指针

C语言中,对数组的操作,是仿照指针的模式进行的。但是需要记住一点,数组不等于指针。对于一维数组a[],指向数组的指针p=a来说,他们之间最大的区别在于,数组方式使用数组名a(同时也是数组的首地址)对数组进行直接的访问和操作,而指针方式使用指针名p对数组进行的是间接的访问和操作。在多数情况下,他们操作结果是相同的,但是也有例外。

如果我们在文件外定义了一个指针p,int *p=a(a是一个整型数组)。在文件内用到p时,需要用extern声明一下,表明p是个外部变量,在外部定义好了。如果我们声明为指针 extern int * p,然后去使用,肯定是没有问题的。但是如果我们声明为数组extern int p[] ,问题就出现了,编译系统处理的时候会使用数组方式对指针进行操作。也就是说,当我们想得到*p,也就是*a,a[0]的值的时候,因为系统把p当作了数组首地址,所以*p并不能得到a[0],得到的是p所存放的地址值,也就是a[0]的地址。这种情况下,一定要使extern声明与定义相匹配。

数组的直接访问数据模式与指针的间接访问数据模式,是两者之间最根本的不同。数组不等于指针。数组通常用于存储固定数目且数据类型相同的元素,数组所占用的内存是隐式分配和删除的,数组中保存数据,并且数组中的每个元素都有唯一且明确的变量名来标识数据,使用数组可以直接访问数据也就是说a[i]只是简单地以a+i为地址取得数据。而指针通常用于动态数据结构,指针变量保存的是数据的地址(其中包括变量的地址,也包括不匿名数据),使用指针访问数据采用的是间接访问模式,即首先取得指针的内容,把它作为地址,然后从这个地址提取数据。如果指针有下标,p[i]就是先去的指针p的内容,然后把指针p的内容加上i作为地址,从中提取数据。指针可以指向匿名数据,所以要学会用指针操作匿名内存,c语言中与内存空间相关的函数为malLOC(), free()。

在定义指针时,编译器并不为指针所指的对象分配内存空间,只是分配指针本身的空间,除非在定义字符指针(必须是指向字符型的)的同时用字符串常量进行初始化。其实就算是这种情况,也可当作是编译器为此字符串常量分配了内存空间后,在为字符指针本身分配了空间,并使字符指针指向字符串常量的首地址。在ANSI C中,初始化指针所创建的字符串常量被定义为只读(?这一点,我用turbo C试了试,好像可以修改)。数组也可以用字符串常量进行初始化,但与指针襄樊,由字符串常量初始化的数组是可以修改的,原因很简单,由字符串常量初始化的数组本来就是一个字符数组,每个字符都有确定的变量名与之对应,所以当然可以修改单个字符了。而初始化指针所创建的字符串常量,其实是匿名的数据,如果你把指向字符串常量的字符指针赋予了其他地址,这个字符串常量显然再也找不到了。

由此可见,数组和指针在编译器处理时是不同的,在运行时的表示形式也是不一样的,并且可能产生不同的代码。对编译器而言,一个数组就是一个地址,一个指针就是一个地址的地址。所以,在外部数组的声明时,在数组的定义(因为数组的定义必然要分配内存空间)时,不能用指针来替代数组。

还有,在下列情况下,对数组的引用不能用指向该数组第一个元素的指针来替代:

1. 数组名作为sizeof()的操作数,因为此时需要的是整个数组的大小,而不是指针所指向的第一个元素的大小;

2. 使用&操作符取数组的地址。&操作符的主要用途是实现传址调用。指针本身就是地址,所以对指针使用&意义不大。

3. 数组是一个字符串常量初始值。这一点上面已经提到,不多说了。字符串常量初始化数组必须一气呵成,不能分成两了语句。也就是说,字符串常量只能对数组进行声明初始化,不能用字符串常量对数组赋值。这点是因为C语言中只能够在数组声明时对它进行初始化(这点没啥原因,也许是因为数组名是不可修改的左值吧),不能对数组名赋值,只能对数组元素逐个赋值。

4. 数组名是不可修改的左值,它的值是数组第一个元素的地址,不可以改变。

二、什么时候数组与指针相同

大多数的时候,数组和指针可以互换。

1. 除了个别情况,表达式中的数组名(数组在使用中,而不是声明中)就是指针

假如我们声明:int a[10], *p, i=2;

就可以通过以下方法来访问a[i] :

a[i];

*(a+i);

p=a ; p[i] ;

p=a ; *(p+i) ;

p=a+i ; *p ;

实际上,对数组的引用如a[i]在编译时总是被编译器改写成*(a+i)的形式。所以如加法一样,取下标操作符的操作数是可以交换的(a[i] 与i[a] 都是正确的,等价的)。

编译器自动把下标值得步长调整到数组元素的大小。对起始地址执行加法操作之前,编译器会负责计算每次增加的步长。这就是为什么指针总是有类型限制,每个指针只能指向一种类型的原因所在。

2. 数组下标总是与指针的偏移量相同

数组下标总是与指针的偏移量相同,所以程序员完全可以使用指针来访问数组,从而绕过下标操作符。在这种情况下,对数组下标范围检查并不能检测所有对数组的访问情况。因此,C语言并不进行下标范围检测。但是我们编写程序的时候,可要小心,不要越界。

在处理以为数组时,指针并不比数组更快。C语言吧数组下标改写成指针偏移量的根本原因是指针和偏移量是底层硬件所使用的基本模型。

3. 作为函数参数的数组名等同于指针

吧作为形参的数组和指针等同起来是出于效率原因的考虑。在函数参数的声明中,数组名被编译器当中指向该数据第一个元素的指针。编译器只向函数传递数组的地址,而不是整个数字的拷贝。隐性转换意味着下面三种函数定义形式是完全相同的:

fun(int *p){...}

fun(int p[]) {...}

fun(int p[10]) {...}

在函数的声明和调用上,使用数组或者指向数组第一个元素的指针都是合法的。

注意,这里第一个元素的含义,这第一个元素可以是数值变量、字符变量、数组、结构体、指针。

三、总结

数组不等于指针,但是数组可以用指针等效;指针始终是指针,指针绝对不可以改写为数组。你可以使用下标方式访问指针,一般是指针作为函数参数时,一般是指针指向的是数组元素时。

在外部声明和定义时,数组不能拿指针来等效,除了数组作为函数参数之外,定义和声明必须匹配。

在使用时,数组基本可以与指针互换。a[i]总是被编译器解释为*(a+i)。

在作为函数参数时,数组可以与指针互换。编译器总是把函数参数的数组修改为指向数组第一个元素的指针。在函数内部获得的事实上都是一个指针。

c语言实际上没有多维数组。只有数组元素是数组的数组。多维数组作为函数参数,传递的指针类型是指向数组的指针。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

万用表是一种可以测量多种项目的便携式仪表,在电子技术中主要用来测量电压、电流与电阻。在电子元器件选用中,它可用来粗略检测元器件的好坏或性能优劣

关键字: 指针 万用表

万用表又称为复用表、多用表、三用表、繁用表等,是电力电子等部门不可缺少的测量仪表,一般以测量电压、电流和电阻为主要目的。万用表按显示方式分为指针万用表和数字万用表

关键字: 指针 万用表 数字万用表

字符串是C语言中最基础的概念,也是最常被用到的。在嵌入式开发中,我们经常要将一些字符串通过串口显示到串口助手或调试终端上,作为信息提示,以便让我们了解程序的运行情况;或者是将一些常量的值转为字符串,来显示到液晶等显示设备...

关键字: 字符串 指针 C 语言

指针使得 C 语言能够更高效地实现对计算机底层硬件的操作,而计算机硬件的操作很大程度上依赖地址,指针便提供了一种对地址操作的方法,在一定意义上,指针是c语言的精髓,所以一定要耐心看完。指针对于很多c语言初学者来说可能难以...

关键字: 指针 C 语言 计算机

有深入理解RTOS原理,或阅读过RTOS源码的同学应该知道:RTOS实现任务间通信通常是由一系列指针进行操作实现的。

关键字: RTOS 指针 数组

实际上函数指针本质也是一个指针,只不过这个指针指向的不是内存中的一段数据而是内存中的一段代码

关键字: 指针 数据 代码

摘  要:数组是程序设计课程中的重点内容,如何使学生灵活熟练地掌握数组,案例内容的设计是教学关键点之一。文中提出一种案例循序递进的教学方法,把学科竞赛中超大数运算问题引入到数组实践教学中。实践结果证明此案例教学法有助于调...

关键字: 案例教学法 实践教学 数组 超大数

C 为什么不加入垃圾回收机制!

关键字: 垃圾回收 指针

记得刚开始工作时,一位高手告诉我,说,longjmp和setjmp玩得不熟,就不要自称为C语言高手。

关键字: 指针 C语言 longjmp

C ++ 的连载教程就到此结束了,所涉及的内容也只是 C++ 中很浅显的一部分。

关键字: C 指针
关闭
关闭