目录
指针的含义:
使用指针
二级指针以及二级指针的传递
指针与一维数组
字符指针与字符数组的初始化
指针与动态内存申请
指针和自增自减运算符
指针的含义:
按变量地址存取变量值的方式称为“直接访问”,如printf("%d",i);scanf("%d",&d);
另一种存取变量的方式称为“间接访问”,即将变量i的地址存放到另一个变量中,在C语言里,指针变量是一种特殊的变量,它用来存放变量的地址。即指针存放的是地址,指针就是地址。
声明与初始化的格式:
基类型 *指针变量名;
例如:int *i_pointer;/ int *a,b,c;//出错原因:不知道是三个指针变量还是一个指针变量。 int *a,*b,*c;//这是正确的
这里&*pointer_1 与 &a 相同,都表示a的地址,即pointer_1.
//&*pointer_1 先执行*pointer_1 来存储A的地址,*pointer_1=a,再&,则会获取a的地址。
*&a会先运行&a,得到a的地址,再进行*运算,则会得到变量a,即显示变量a的内容。
按值运算和按地址运算:
在C语言里,若是对值操作,让一个变量的值赋给另一个变量,就会临时生成一个临时地址,接下来就只是对临时地址操作,这时候两个变量还是两个不同的地址。如果是在操作时有*或&操作符,则是对地址进行操作,此时一个变量赋值给另一个变量,是对同一个地址进行不同的操作,两个变量指向同一个地址。
有关引用的使用方法的实例:
#include#define N 10 void max_min(int a[],int n,int *max, int *min);//函数原型 int main() { int b[N],i,big,small; printf("Enter %d numbers: ",N); for ( i = 0; i < N; i++) { scanf("%d",&b[i]); } max_min(b, N, &big, &small);//调用函数max_min printf("Largest: %dn",big); printf("Smallest: %dn",small); return 0; } void max_min(int a[], int n, int *max, int *min) { int i; *max = *min = a[0]; for ( i = 1; i < n; i++) { if (a[i]> *max) { *max=a[i]; } else if (a[i]< *min) { *min = a[i]; } } }
输出结果:
Enter 10 numbers: 34 82 49 102 7 94 23 11 50 31
Largest: 102
Smallest: 7
使用指针
1. printf("%dn",*p);//输出i的值
2. *p=2;//等同于i=2;
3. q=p;//把p的内容(即i的地址)复制给q,p和q同时指向i;注意:这里没加"*"符号。
4. *q=*p;//假如指向j,那么这条语句就是将i的值复制给j。
5. &a[i]是指向a中元素i的指针。
二级指针以及二级指针的传递
二级指针也是一种指针,只服务于一级指针的传递与偏移。
指针与一维数组
思考:为什么在数组那一篇文章里,一维数组在函数调用进行传递时,它的长度子函数无法知道呢?这是由于一维数组名中存储的是数组的首地址。数组名c中存储的地址是0x0015faaf4,所以子函数change中其实传入了数组的地址,不知道数组有多长。
指针法:定义一个指针变量时,指针变量的类型要和数组类型保持一致,通过取值操作,就可将“h”改成"H"。
下标法:获取数组元素时,也可以通过取下标的方式来获取数组元素并进行修改。
字符指针与字符数组的初始化
字符指针可以初始化赋值一个字符串,字符数组初始化也可以赋值给一个字符串。
例如:char *p="hello",是把字符串常量"hello"的首地址赋给P。char c[10]= "hello'"等同于strcpy("hello");
指针与动态内存申请
如果数据存储在栈空间中,那么栈的大小在编译时是确定的。如果使用的空间大小不确定,那么久要使用堆空间。
#include#include #include int main() { int i; char *p; scanf("%d",&i);//输入要申请的空间的大小 p=(char*)malloc(i);//使用malloc动态申请堆空间 strcpy(p,"malloc success"); puts(p); free(p);//free时必须使用malloc申请时返回的指针值,不能进行任何偏移 printf("free successn"); return 0; }
#includeint main() { char *p = "hello" ;//把字符串常量“hello"的首地址赋给p char c[10]="hello";//等价于strcpy(c,"hello"); printf("c[0]=%cn",c[0]); printf("p[0]=%cn",p[0]); c[0]='H'; p[0]='H';//加上这一句会显示错误,因为不可以对常量区数据进行修改。 return 0; }
也就是说,p里面存储的是’h'的地址,当‘hello’被赋值给p后,hello就变成了一个字符串常量,如果内存存储的是字符串常量,那么这里的权限就是可读不可写。所以p[0]='H‘;会报错。
而char c[0]="hello"这一步,并不是直接c直接指向"hello"常量,而是,hello+ 都存储在栈空间里,然后复制一份给c,所以c[0]='H'后,我们会发现存储"hello"的栈里的数据变成了"Hello",而c的地址里的数据还是"hello"。我们可以对栈空间里的数据是可读可写的。
但是,如果增加的两句是p="world";c="world";那么这里面非法的是c="world",此时c不是一个变量,不可以重新赋值。p="world"这一句是将原来指向"hello"的p指针指向了"world"。也就是说,不可以指针里的常量进行修改,但是可以改变指针指向。
指针和自增自减运算符
指针与自增自减结合,不是简单的像其它的变量值一样,直接加一,而是找到下一个地址。例如:在下面的例子里,p存储了a数组的所有的数据的地址,如果此时输出*p,p会指向a数组的开始数据,即a[0],执行p++ ,p就会指向下一地址即a[1].
当然*p ++会先执行*p,再执行p++。
include//指针与自增自减 //只有比后增优先级高的 操作符,才会作为一个整体,如(). int main() { int a[3]={2,5,4}; int *p; int j; p = a; j = *p++;//先把*p的值赋给j,然后对p加一 printf("a[0] =%d, j=%d,*p=%dn",a[0],j,*p); return 0; }
通过上面的消息也可以看出:输出*p输出的是p地址里存储的数据。
include//指针与自增自减·升级一下 //只有比后增优先级高的操作符,才会作为一个整体,如(). int main() { int a[3]={2,5,4}; int *p; int j; p = a; j = *p++;//先把*p的值赋给j,然后对p加一 printf("a[0] =%d, j=%d,*p=%dn",a[0],j,*p); printf("p[1]=%dn",p[1]); j = p[0]++;//先把p[0]赋给j,然后对p[0]加1。 printf("a[0]=%d,j=%d,*p=%dn",a[0],j,*p); return 0; return 0; }



