人人学编程-C语言入门 C语言的灵魂:指针,及其与数组的关系

摘要: 指针提供了一种用来使用地址的符号方法。由于计算机的硬件指令很大程度上依赖于地址,所以指针使您能够以类似于计算机底层的表达方式来表达自己的意愿。这使得使用了指针的程序能够更高效的工作。指针能够很有效的处理数组。数组标记实际上是一种变相使用指针的形式。

相关阅读:获取变量地址

我们举一个这种变相使用的例子:

数组名同时也是该数组首元素的地址。

也就是说,如果flizny是一个数组,下面的式子是正确的:

flizny == &flizny[0] //数组名是该数组首元素的地址

flizny和&flizny[0]都代表首元素的地址。

两者都是常量,因为在程序运行过程中它们保持不变。

然而可以把它们作为赋给指针变量的值,然后您可以修改指针变量的值。如程序pnt_add.c所示,请注意给指针加上一个数的时候,它的值会发生什么变化?(指针说明符%p通常以十六进制形式显示值)。

程序 pnt_add.c程序

//pnt_add.c -- 指针加法 #include #define SIZE 4 int main(void) { short dates[SIZE]; short *pti; short index; double bills[SIZE]; double *ptf; pti = dates; //把数组地址赋给指针 ptf = bills; printf("%23s %10s\n","short","double"); for (index=0;index

输出结果如下:

第二行打印两个数组的起始地址,第3行是地址加1的结果,等等。请注意地址是16进制的,因此,30比2f大1,比28大8。怎么回事?

ox0064fd20 + 1 等于 0x0064fd22 ?

0x0064fd30 + 1 等于 0x0064fd38 ?

真奇怪!我们的系统是按字节编址的,但是short类型使用2个字节,double类型使用8个字节。

在C中,对一个指针加1的结果是对该 指针增加一个存储单元(storage unit)。

对于数组而言,地址会增加到下一个元素的地址,而不是下一个字节。这就是在声明指针时必须声明它所指向对象的类型。计算机需要知道存储对象所用的字节数,所以只有地址信息是不够的(即使指针是指向标量的,也需要声明指针类型;否则*pt操作是不能正确返回数值的)。

现在我们能够清楚地定义指向int的指针、指向float的指针,以及指向其他数据对象的指针:

指针的数值就是它所指向的对象的地址。

地址的内部表示方式是由硬件来决定的。很多种计算机都 是以字节编址的,这意味着对每个内存字节顺序进行编号。对于包含多个字节的数据类型,比如double类型的变量,对象的地址通常指的是其首字节的地址。

在指针前使用运算符" * "就可以得到该指针所指向的对象的数值。

对指针加1,等价于对指针的值加上它指向的对象的字节大小。

下面的等式体现出了C的优点:

dates + 2 == &dates[2]; //相同的地址

*(dates + 2) == dates[2]; //相同的值

这些关系总结了数组和指针间的密切关系:

可以用指针标识数组的每个元素,并得到每个元素的数值。从本质上说,对同一个对象有两种不同的符号表示方法。C语言标准在描述数组时,确实借助了指针的概念。

例如,定义ar[n]时,意思是*(ar+n),即“寻址到内存中的ar,然后移动n个单位,再取出数值”。

顺便提一下,请注意区分*(dates + 2)和*dates + 2。

间接运算符的优先级高于+,因此后都等价于*(dates)+2。

*(dates+2) //dates的第3个元素的值

*dates + 2 //第一个元素的值和2相加

理解了数组和指针的关系,编程时就可以方便地选择两者中任意一种方法。

程序 day_mon3.c 程序

/*day_mon3.c --使用指针符号*/ #include #define MONTH 12 int main(void) { int days[MONTH] = ; int index; for (index=0;index

此处,days是数组首元素的地址;days+index是元素days[index]的地址;*(days+index)是这个元素的值,与days[index]等价。

下节早知道:保护数组内容不被意外改变。

摘要: 指针提供了一种用来使用地址的符号方法。由于计算机的硬件指令很大程度上依赖于地址,所以指针使您能够以类似于计算机底层的表达方式来表达自己的意愿。这使得使用了指针的程序能够更高效的工作。指针能够很有效的处理数组。数组标记实际上是一种变相使用指针的形式。

相关阅读:获取变量地址

我们举一个这种变相使用的例子:

数组名同时也是该数组首元素的地址。

也就是说,如果flizny是一个数组,下面的式子是正确的:

flizny == &flizny[0] //数组名是该数组首元素的地址

flizny和&flizny[0]都代表首元素的地址。

两者都是常量,因为在程序运行过程中它们保持不变。

然而可以把它们作为赋给指针变量的值,然后您可以修改指针变量的值。如程序pnt_add.c所示,请注意给指针加上一个数的时候,它的值会发生什么变化?(指针说明符%p通常以十六进制形式显示值)。

程序 pnt_add.c程序

//pnt_add.c -- 指针加法 #include #define SIZE 4 int main(void) { short dates[SIZE]; short *pti; short index; double bills[SIZE]; double *ptf; pti = dates; //把数组地址赋给指针 ptf = bills; printf("%23s %10s\n","short","double"); for (index=0;index

输出结果如下:

第二行打印两个数组的起始地址,第3行是地址加1的结果,等等。请注意地址是16进制的,因此,30比2f大1,比28大8。怎么回事?

ox0064fd20 + 1 等于 0x0064fd22 ?

0x0064fd30 + 1 等于 0x0064fd38 ?

真奇怪!我们的系统是按字节编址的,但是short类型使用2个字节,double类型使用8个字节。

在C中,对一个指针加1的结果是对该 指针增加一个存储单元(storage unit)。

对于数组而言,地址会增加到下一个元素的地址,而不是下一个字节。这就是在声明指针时必须声明它所指向对象的类型。计算机需要知道存储对象所用的字节数,所以只有地址信息是不够的(即使指针是指向标量的,也需要声明指针类型;否则*pt操作是不能正确返回数值的)。

现在我们能够清楚地定义指向int的指针、指向float的指针,以及指向其他数据对象的指针:

指针的数值就是它所指向的对象的地址。

地址的内部表示方式是由硬件来决定的。很多种计算机都 是以字节编址的,这意味着对每个内存字节顺序进行编号。对于包含多个字节的数据类型,比如double类型的变量,对象的地址通常指的是其首字节的地址。

在指针前使用运算符" * "就可以得到该指针所指向的对象的数值。

对指针加1,等价于对指针的值加上它指向的对象的字节大小。

下面的等式体现出了C的优点:

dates + 2 == &dates[2]; //相同的地址

*(dates + 2) == dates[2]; //相同的值

这些关系总结了数组和指针间的密切关系:

可以用指针标识数组的每个元素,并得到每个元素的数值。从本质上说,对同一个对象有两种不同的符号表示方法。C语言标准在描述数组时,确实借助了指针的概念。

例如,定义ar[n]时,意思是*(ar+n),即“寻址到内存中的ar,然后移动n个单位,再取出数值”。

顺便提一下,请注意区分*(dates + 2)和*dates + 2。

间接运算符的优先级高于+,因此后都等价于*(dates)+2。

*(dates+2) //dates的第3个元素的值

*dates + 2 //第一个元素的值和2相加

理解了数组和指针的关系,编程时就可以方便地选择两者中任意一种方法。

程序 day_mon3.c 程序

/*day_mon3.c --使用指针符号*/ #include #define MONTH 12 int main(void) { int days[MONTH] = ; int index; for (index=0;index

此处,days是数组首元素的地址;days+index是元素days[index]的地址;*(days+index)是这个元素的值,与days[index]等价。

下节早知道:保护数组内容不被意外改变。

欢迎各位加入我创建的一个C\C++学习交流群,想要和大神交流,想要完整的学习资料外加视频的,系统的好好学学,不容错过:三七八零五三五零二,都是免费的,一起来创造良好的学习氛围!

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180105A0X7UQ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券