指针提供了一种用来使用地址的符号方法,使得使用指针的程序能够高效运行,特别是能够有效地处理数组。
简单讲一下数组的指针。
首先数组的名字就是该数组首个元素的地址,num是数组名字的话
num==&num[0];
然后在C中,对一个指针加1的结果是对该指针增加一个存储单元,读于数组来说就是地址会增加到下一个元素,而不是增加一个字节
num+1 ==&num[1];
在声明数组参量时,如果实际参数是一个数组名,那么形式参量必须是与之相匹配的指针。
定义函数时,这两种等价
int sum(int *num,n)
{
};
int sum(int num[],n)
{
};
在原型中甚至名字都可以省略,以下四种等价
int sum(int *num,n);
int sum(int *,n);
int sum(int num[],n);
int sum(int [],n);
利用指针我们可以更好的传递数值进入函数中将原数值变成需要的数值,省去麻烦的return,但是有时候我们并不希望原始数据被改变。
那么就在函数原型和定义的形式参数声明中使用关键字const。
#include <stdio.h>
int main(void )
{
const double num[] ={11.3,12.4,55.1};
num[1]=2.5;
return 0;
}
这里想要改变常量数组的值,结果就报错了
l-value specifies const object
同理指向常量的指针也无法修改它所指向的值。
当能明确的分清到底是数值还是地址的时候,指针的初步学习也就完成了。
一维数组还好辨认,二维就有点困难了。
#include <stdio.h>
int main(void )
{
int num[] ={1,2,3,4,5,6};
printf("num=%p\n",num);
printf("num+2=%p\n",num+2);
printf("*(num+2)=%d\n",*(num+2));
printf("*(num+2)+1=%d\n",*(num+2)+1);
return 0;
}
结果
num=0019FF18
num+2=0019FF20
*(num+2)=3
*(num+2)+1=4
#include <stdio.h>
int main(void )
{
int num[3][3] ={
{1,2,3},
{4,5,6},
{7,8,9}};
printf("num=%p\n",num); /*等同于num[0]的地址*/
printf("num+2=%p\n",num+2); /*等同于num[2]的地址*/
printf("*(num+2)=%p\n",*(num+2)); /*等同于num[2][0]的地址*/
printf("*(*(num+2))=%d\n",*(*(num+2))); /*等同于num[2][0]的值也就是7*/
printf("*(num+2)+1=%p\n",*(num+2)+1); /*等同于num[2][1]的地址*/
printf("*(*(num+2)+1)=%d\n",*(*(num+2)+1)); /*等同于num[2][1]的值*/
return 0;
}
结果如下
num=0019FF0C
num+2=0019FF24
*(num+2)=0019FF24
*(*(num+2))=7
*(num+2)+1=0019FF28
*(*(num+2)+1)=8
此外一个存放字符串的数组和指向字符串的指针(其实也是指向字符串的第一个字符)
两者的差别不太大
char heart[] = "I am newbee";
char *head = "I am newbee";
数组名heart是个常量,指针head是个变量,两者都可以用数组符号
for(i=0;i<6;i++)
putchar(heart[i]);
putchar("\n");
for(i=0;i<6;i++)
putchar(head[i]);
putchar("\n");
其次两者都可以用指针加法,但只有指针能用增量运算符,因为指针是变量。
for(i=0;i<6;i++)
putchar(*(heart+i));
putchar("\n");
for(i=0;i<6;i++)
putchar(*(head+i));
putchar("\n");