数组指针和普通指针区别 指针数组如何赋值
- 软件开发
- 2023-09-21
- 55
各位老铁们,大家好,今天由我来为大家分享数组指针和普通指针区别,以及指针数组如何赋值的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持...
各位老铁们,大家好,今天由我来为大家分享数组指针和普通指针区别,以及指针数组如何赋值的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!
C语言中指针数组和数组指针、函数指针、指向函数的指针等等该怎么理解
要理解这些问题首先需要理解什么是指针和指针变量。
在C语言中我们可以认为指针就是地址,不过是某一个具体内存单元的地址。
如我们在c语言中定义了一个int型变量a:
inta;
那么计算机就会给a分配4个字节的地址(在vc++中,在某些版本的c语言中,可能是2个字节)来存放a的值。由于在内存中每个字节都有一个地址,那么哪个地址是a的地址呢?我们不能同时用4个地址来表示a的地址吧,所以在c语言中,我们拿这块空间(4个字节)的第一个字节的地址当作变量a的地址,也就是首地址。
然后我们在定义一个指针变量,如:
int*p;
再用取地址运算符把a的首地址取出来赋值给指针变量p,如:
p=&a;
现在指针变量p里存放的就是a的地址,我们就称p是a的指针。
所以,指针数组是什么?
就是一个数组里,每个数组元素都存放的是指针类型的值,也就是地址值。而不是基本数据类型,如:整型、实型、字符型。定义一个指针数组的方法如下:
int*pa[10];
其中pa是数组名称,10为数组大小。
那么,数组指针呢?
根据上面所说的,指针就是一块空间的首地址。所以,数组指针就是——数组的首地址。在c语言中,我们可以拿数组名表示数组的首地址。我们可以如下所示,将一个指针变量指向数组:
inta[10],*p;
p=a;
当然,由于数组的第一个元素是a[0],所以a[0]的地址也是数组的地址,所以,我们也可以这样写:
p=&a[0];
这样,我们就可以说,p是数组a的指针。
至于函数指针,就是指向函数的指针,因为在c语言中,函数实际是放在一段内存中的,所以只要我们找到了这段内存的起始地址,也就找到了函数,所以我们也可以拿一个指针变量,存放函数的首地址,从而让一个指针指向某个函数。
定义并使用一个函数指针的方法如下:
intfun(intx);/*声明一个函数*/
int(*f)(intx);/*定义一个函数指针*/
f=fun;/*将fun函数的首地址赋给指针f*/
或者使用下面的方法将函数地址赋给函数指针:
f=&fun;
赋值时函数fun不带括号,也不带参数,由于fun代表函数的首地址,因此经过赋值以后,指针f就指向函数fun(x)的代码的首地址。
这个时候f就成为了指向函数的指针。
我们就可以像下面这样,直接通过指针来调用函数了:
c=(*f)(a);/*通过指针f来调用函数fun*/
谢谢邀请,喜欢请关注我。
C语言数组下标和指针的关系
指针与数组是C语言中很重要的两个概念,它们之间有着密切的关系,利用这种关系,可以增强处理数组的灵活性,加快运行速度,本文着重讨论指针与数组之间的联系及在编程中的应用。1.指针与数组的关系当一个指针变量被初始化成数组名时,就说该指针变量指向了数组。如:charstr[20],*ptr;ptr=str;ptr被置为数组str的第一个元素的地址,因为数组名就是该数组的首地址,也是数组第一个元素的地址。此时可以认为指针ptr就是数组str(反之不成立),这样原来对数组的处理都可以用指针来实现。如对数组元素的访问,既可以用下标变量访问,也可以用指针访问。2.指向数组元素的指针若有如下定义:inta[10],*pa;pa=a;则p=&a[0]是将数组第1个元素的地址赋给了指针变量p。实际上,C语言中数组名就是数组的首地址,所以第一个元素的地址可以用两种方法获得:p=&a[0]或p=a。这两种方法在形式上相像,其区别在于:pa是指针变量,a是数组名。值得注意的是:pa是一个可以变化的指针变量,而a是一个常数。因为数组一经被说明,数组的地址也就是固定的,因此a是不能变化的,不允许使用a++、++a或语句a+=10,而pa++、++pa、pa+=10则是正确的。由此可见,此时指针与数组融为一体。3.指针与一维数组理解指针与一维数组的关系,首先要了解在编译系统中,一维数组的存储组织形式和对数组元素的访问方法。一维数组是一个线形表,它被存放在一片连续的内存单元中。C语言对数组的访问是通过数组名(数组的起始地址)加上相对于起始地址的相对量(由下标变量给出),得到要访问的数组元素的单元地址,然后再对计算出的单元地址的内容进行访问。通常把数据类型所占单元的字节个数称为扩大因子。实际上编译系统将数组元素的形式a[i]转换成*(a+i),然后才进行运算。对于一般数组元素的形式:<数组名>[<下标表达式>],编译程序将其转换成:*(<数组名>+<下标表达式>),其中下标表达式为:下标表达式*扩大因子。整个式子计算结果是一个内存地址,最后的结果为:*<地址>=<地址所对应单元的地址的内容>。由此可见,C语言对数组的处理,实际上是转换成指针地址的运算。数组与指针暗中结合在一起。因此,任何能由下标完成的操作,都可以用指针来实现,一个不带下标的数组名就是一个指向该数组的指针。4.指针与多维数组用指针变量可以指向一维数组,也可以指向多维数组。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。例如,在一个三维数组中,引用元素c[i][j][k]的地址计算最终将换成:*(*(*(c+i)+j)+k)。了解了多维数组的存储形式和访问多维数组元素的内部转换公式后,再看当一个指针变量指向多维数组及其元素的情况。1指向数组元素的指针变量若有如下说明:inta[3][4];int*p;p=a;p是指向整型变量的指针;p=a使p指向整型二维数组a的首地址。*(*(p+1)+2)表示取a[1][2]的内容;*p表示取a[0][1]的内容,因为p是指向整型变量的指针;p++表示p的内容加1,即p中存放的地址增加一个整型量的字节数2,从而使p指向下一个整型量a[0][1]。2指向由j个整数组成的一维数组的指针变量当指针变量p不是指向整型变量,而是指向一个包含j个元素的一维数组。如果p=a[0],则p++不是指向a[0][1],而是指向a[1]。这时p的增值以一维数组的长度为单位。5.指针与字符数组C语言中许多字符串操作都是由指向字符数组的指针及指针的运算来实现的。因为对于字符串来说,一般都是严格的顺序存取方式,使用指针可以打破这种存取方式,更为灵活地处理字符串。另外由于字符串以′\0′作为结束符,而′\0′的ASCII码是0,它正好是C语言的逻辑假值,所以可以直接用它作为判断字符串结束的条件,而不需要用字符串的长度来判断。C语言中类似的字符串处理函数都是用指针来完成,使程序运行速度更快、效率更高,而且更易于理解。
指针数组和数组指针有什么区别
指针数组和数组指针的区别如下:
1.定义方式不同:指针数组是一个元素为指针类型的数组,而数组指针是一个指向数组的指针。
2.数据类型不同:指针数组中每个元素都是一个指针,而数组指针本身是一个指向特定类型数据的数组。
3.访问元素不同:在访问指针数组时,需要首先访问该元素所在的位置,然后使用间接引用操作符(*)来访问该元素所指向的值;在访问数组指针时,可以直接使用下标操作符[]访问其所指向的数组中的元素。
4.内存布局不同:对于指针数组,每个元素都是一个独立的内存位置,其值存储了相应对象或变量地址;而对于数组指针,它本身也是一个变量,并且存储了整个数组的地址。
指针和指针变量的区别是什么
1.概念不同:指针是一个用于存储内存地址的变量类型,而指针变量则是用于存储指针类型的变量。
2.类型不同:指针可以是任何类型,包括整型、浮点型、字符型、结构体等,而指针变量是指向某种特定类型的指针。
3.存储方式不同:指针变量会在栈内存中为其分配空间,而指针所指向的内存地址则可能位于堆内存、栈内存或全局内存等不同的位置。
4.操作方式不同:指针可以进行指针运算和解引用操作,而指针变量只能进行指针赋值等基本操作。
数组指针的语法形式
数组指针,指的是数组名的指针,即数组首元素地址的指针。即是指向数组的指针。例:int(*p)[10];p即为指向数组的指针,又称数组指针。
C语言的指针不是地址吗为什么地址还要区分类型指针的加法也好难,该怎么理解呢
谢谢邀请。
题主的疑问应该是,C语言的指针变量里存放的是地址,而地址明明是一个整数,为什么整数还要区分类型?至于指针的加法,题主应该是注意到了有时候1+1并不等于2,对不?其实这并没有什么难的,请继续往下看。
为何要有不同类型的指针变量稍稍思考一下,应该能够发现,C语言中的指针是通过修改内存来修改变量的值的。
既然指针是通过修改内存来修改变量的值的,那么,一个指针一次修改多少内存呢?这就涉及到指针的类型了。请看例子,相关C语言代码如下:
对于数组i[8],i其实就表示这个数组的首地址,所以可以直接把它赋值给指针变量p1。这样一来,我们就可以通过p1来修改数组i了。
指针p1是signedchar*类型的,通过p1修改i所在内存时,一次修改sizeof(signedchar)字节,也即1字节。那么,p1+1指向的就是i的第二个元素(i[1]),执行*(p1+1)=5;以后,i[1]就等于5了。
按照这个逻辑,p2是int*类型的指针变量,请看上图,通过p2访问数组i时,一次访问的实际上是sizeof(int)=4字节内存。所以*(p2+1)=9;实际上修改的是i的第5~8字节。
我们把C语言代码写完整些,通过p1修改后,把i全部打印出来;通过p2修改后,再把i全部打印出来,请看如下C语言代码:
编译并执行这段C语言代码,得到如下输出:
1534567815349000指针的加法看到这里,你可能会有疑问了,i的地址为4000,那p1和p2指向的也是4000,p1+1指向4001地址,这没什么好说的。但是p2+1指向的却是4004?4000+1等于4004,这不是扯淡吗?!
这还真不是扯淡,题主可以看看我之前关于C语言数据类型的问答或者文章,应该能够注意:“+”运算符要求两边的操作数是同一类型的,如果不同则会自动转换。
p1和p2是指针类型的,而“+1”的这个“1”是整型的,因此在做加法之前,会有自动数据类型转换的过程。p1是signedchar*型的指针变量,所以“+1”就相当于“+1xsizeof(signedchar)”,因此p1+1=4001。类似的,p2加上整型1就相当于“+1xsizeof(int)”,因此p2+1=4004。
为了验证我们的分析,下面写C语言代码做实验,我们分别定义signedchar*型的指针变量p1和int*型的指针变量p2,均赋值为1,然后分别对p1和p2加一,打印它们原来的值,和加一后的值,请看如下C语言代码:
编译并执行这段C语言代码,得到如下输出:
p1=0x1,p1+1=0x2p2=0x1,p2+1=0x5这就验证了我们的分析。类似的,读者可以自行分析long*、float*、double*等任意类型的指针变量的加法运算。
可以将指针的加数“1”看作有“单位”的,单位大小取决于指针的类型。这样就好理解“1+1”不等于2的情况了,因为1千克+1毫克不等于2千克,对不?
作为延伸,下面再讨论一些C语言指针的特性。
指针变量占多少内存空间?既然指针变量存储的是内存地址,那么指针变量的位宽就应该保证能够存储最大的地址。例如在大多数32位计算机中,指针变量的位宽为4字节,因为多数情况下,在32位计算机中,最大的内存地址为0xffffffff,至少需要4字节才能完整保存。相应的,在大多数64位计算机中,指针变量的位宽为8字节。
指针这么强,能操作任意地址码?很多程序员都说,某类型的变量,一定不能用其他类型的指针操作。这句话其实并不严谨,例如上面举的例子中的char类型数组i[8],我们完全可以使用int*p2指针把它当做两个int型变量使用。
只不过一定要小心p2别超过i[8]的范围了,p2+2指向的就是数组i后的地址了。这里可能存储着非常重要的信息,如果使用p2+2把这部分的内容修改了,程序出现段错误退出还好,要是没有报错,却给出了错误结果就麻烦了,这种错误非常难发现,所以在开发阶段就应该小心处理。
按照上面的分析,在定义局部指针变量时,如果忘了对它初始化,局部变量的值是任意的,这也就是说它可能指向任意地方,这时如果使用它,也有可能出现难以发现的错误。
这种指向不确定地址的指针,程序员习惯称为“野指针”。
为了避免出现野指针,在定义指针变量时就应该给它明确的初值,例如:
就是把地址0转换成指针类型,称为空指针,它的特殊之处在于,操作系统不会把任何数据保存在地址0及其附近,也不会把地址0~0xfff的页面映射到物理内存,所以任何对地址0的访问都会立刻导致段错误。*p=0;会导致段错误,就像放在眼前的炸弹一样很容易找到,相比之下,野指针的错误就像埋下地雷一样,更难发现和排除,这次走过去没事,下次走过去就有事。
void*指针常常被称作万能指针,限于篇幅,以后再讨论。
欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。
OK,关于数组指针和普通指针区别和指针数组如何赋值的内容到此结束了,希望对大家有所帮助。
本文链接:http://xinin56.com/ruanjian/29350.html