指针学习资料(zollty-2009)
1.指向普通变量或者某个数或者字符串。例如
int j,a[10];
int *pointer_1,*pointer_2;
pointer_1=&j;
pointer_2=&a[7];
2.指针作为函数参数。例如
(主函数部分)
pointer_1=&a;pointer_2=&b;
if(a<b) swap(pointer_1,pointer_2);
(交换两数的函数)
void swap(int *p1,int *p2)
{ int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
}
swap接受主函数传来的两个数a和b的地址,用p1和p2去指代,然后交换p1和p2的内容,则在内存上引起了改变,所以原来的a和b所对应的值改变。
3.指向数组首地址【例1】
对于一维数组:p=a; 调用:*(a+i)或者*(p+i)
对于二维数组:p=a[0]; 调用:*(a[0]+i)或者*(p+i)
4.指向数组的每行【例2】
形如:
int a[3][4];
int (*p)[4]; p=a;
调用:*(*(p+i)+j)
5. 指向函数。例如
int max(int x,int y);
n=max(a,b);
可以改作:
int (*p)(int,int);
p=max;
n=p(a,b);
6.返回指针值的函数。例如
int *a(int x,int y);
7.指针数组。【例3】
它是一个数组,例如
int *p[4];
char *name[]={"BASIC","C++","PASCAL","COBOL","SQL"};
8.指向指针的指针【例4】
形如 char **p;
9.指针的运算
(1)减法:如果两个指针指向同一数组,则两个指针之差为它们之间间隔的元素个数,比如p1指向a[1],p2指向a[4],则p2-p1=3。而p1+p2无意义;
(2)比较,>、<、=,比较的是同一数组中的元素的先后顺序;
(3)赋值,同类型的指针才能相互赋值,若p1为int型,p2为float型,则可以强制转换p1=(int *)p2;
(4)可以令p=NULL,即使指针指向地址为0的单元,因为指针在未赋值以前指向的是一个未知的地址,这是非常危险的,所以不妨在引用它以前就把NULL赋值给它。
【例】
1.普通指针指向多维数组
#include <iostream>
using namespace std;
int main()
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for(p=a[0];p<a[0]+12;) //a[0]代表数组a[3][4]的首地址,而a代表的是数组第一行的首地址,所以指针a与指针a[0]不同.
cout<<*p++<<" ";
cout<<endl;
return 0;
}
2.行指针指向多位数组
形如(*p)[10],用法为*(*(p+i)+j)
#include <iostream>
using namespace std;
int main()
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int (*p)[4],i,j;
cin>>i>>j;
p=a; //a代表的是数组第一行的首地址.
cout<<*(*(p+i)+j)<<endl;
return 0;
}
3.用来装字符串的数组
方法一:(指针法)
#include <iostream>
using namespace std;
int main()
{ char *name[]={"BASIC","C++","PASCAL","COBOL","SQL"};
cout<<name[0]<<endl;
return 0;
注意:输出的时候用的是name[0]而不是name或者*name[0],后面(例4)将说明原因。
}
方法二:(字符数组法)
#include <iostream>
using namespace std;
int main()
{ char name[][30]={"BASIC","C++","PASCAL","COBOL","SQL"};
cout<<name[0]<<endl;
return 0;
}
注意:方法二不适合类似于int a[2][3]={ {5,8,6},{3,2,4} };的数组(此时若想输出a[0]则是错误的做法)。
方法三:(字符串数组法)
#include <iostream>
#include <string>
using namespace std;
int main()
{ string name[]={"BASIC","C++","PASCAL","COBOL","SQL"};
cout<<name[0]<<endl;
return 0;
}
4.
#include <iostream>
using namespace std;
int main()
{ char **p;
char *name[]={"BASIC","PASCAL","C++","COBOL","SQL"};
p=name+2;
cout<<*p<<endl;
cout<<**p<<endl;
return 0;
}
分析:*p=name[2]= "C++"的首地址,(通常所说一个字符串的“地址”实际上指的是它的“首地址”或者“起始地址”),用cout 输出的不是字符串的首地址而是整个字符串(只要把一个字符串的起始地址给它,cout就一直往后面输出,直到遇到结束符'\0'为止),
为了证明这一点,请看:string a=“finish”;cout<<a<<endl;变量a中只是存放的“finish”的首地址,但是用cout却是把整个“finish”字符串全部输出。故:
例4,第一个*p输出"C++",第二个**p代表"C++"首地址的内容,即C。
例3中,name[0]为"BASIC"的首地址,输出"BASIC",若换成*name[0]则输出B,若换成name则代表的是整个数组的首地址(而不是单个字符串"BASIC"的地址),所以此时输出的是整个数组的首地址。若用*name则输出整个数组的首地址的内容,即"BASIC"(可见字符串的首地址内容为单个字符,一维数组首地址的内容为它的第一个元素,对于二维数组,比如a[3][4],a代表的是第一行的地址,所以cout<<a输出第一行的地址,而cout<<*a则是错误的用法,因为不可能将第一行的所有元素全部输出,提醒:注意一维数组和二维数组的区别)。
C/C++指针实战经验(zollty-2014)
一、两个典型例子
测试环境A:
电脑:笔记本电脑,WIN 7 32位 , Intel i7-2640 2.8GHz CPU,4G内存
软件:VC++ 6.0
1、指针和数组
#include <iostream> using namespace std; int main() { int a[2]={2,8}; //一维数组 int *p; //指向一维数组的指针 p=a; //等价于p=&a[0] //调用方式:*(p+i)或*(a+i) cout<<*(++p)<<endl; return 0; }
蓝色部分输出结果为:
8
如果换成:
cout<<*(p++)<<endl;
则输出:
2
还有一种常见用法:
cout<<*p++<<endl;
其实是上面那种的简写,仍然等于2
2、下面程序的输出是
#include<iostream > using namespace std; void prt(int *y, int *z) { cout<<++*y<<","<<*(z++)<<endl; } int b=40; int c=20; int main() { prt(&b,&c); // 41 20 prt(&b,&c); // 42 20 return 0; }
输出:
41,20
42,20
解析:*(z++)这是指针地址后移一位,不影响*z的值。前者,++*y则会对指向的值造成影响。