1、要区分指针的类型和指针所指向的类型
1.1指针的类型:把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。
eg: int *a;去掉‘a’,得到“int *”,所以该指针的类型就是int *,即该指针是一个指向整型变量的指针;
char *str;去掉“str”,得到"char *",所以该指针的类型就是char *,即该指针是一个指向char型变量的指针;
int **ptr;去掉“ptr”,得到“int **”,故改指针的类型就是“int **,即该指针是一个指向整型指针变量的指针”
int (*ptr)[3];去掉“ptr”,得到“int(*)[3]”,故改指针的类型就是int(*)[3],即该指针是一个指向整型数组的指针。
1.2指针所指向的类型:把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。
eg:int *a;去掉‘a’和‘*’,得到“int”,故该指针所指向的类型是int型;
char *str;去掉“str”和‘*’,得到“char”,故该指正指向的类型是char型;
int **ptr;去掉“ptr”和‘*’,得到“int *”,故该指针指向的类型是int *型;
int (*ptr)[3];去掉“ptr”和‘*’,得到int [3],故该指针指向的是int [3]型。
2、要理解‘*’在不同场合的不同意义
1 void main() 2 { 3 int *a; 4 int b=10; 5 6 a=&b; 7 8 printf(”%d“,*a); 9 }
第3行int *a(定义的时候)‘*’只是表示此时定义的这个变量是指针变量
第8行中的*a,其中的‘*’表示”指向“,”*a“表示指针变量a所指向的变量,也就是b;
3、不能给野指针瞎赋值
eg:
1 void swap(int *p1,int *p2) 2 { 3 int *temp; 4 *temp=*p1; 5 *p1=*p2; 6 *p2=*temp; 7 }
第3行定义了一个指向整型变量的指针temp,接下来在第4行就给*temp赋值。这是错误的。
因为*temp是指针temp所指向的变量,但是由于未给temp赋值,所以temp并没有确定的值,所以temp所指向的内存单元也就是不可预见的。那么对*temp赋值就是向一个未知的存储单元赋值,但是这个未知的存储单元有可能是一个存放着重要数据的单元,这样就会造成系统运行错误。
4、数组名和指针变量的区别
1 int i, *pa, a[] = {3,4,5,6,7,3,7,4,4,6}; 2 pa = a; 3 for (i = 0; i <= 9; i++) 4 { 5 printf("%d ", *pa); 6 pa++; /*注意这里,指针值被修改*/ 7 }
如上述代码所示,在循环体中我们采用pa++来输出数组中所有元素,但是如果将循环体中的pa改成a还对吗?
答案是不对,为什么呢?因为pa是一个指针变量,而数组名a实质上是一个指针常量,常量的值是不允许修改的,其指向的是数组的首地址。
5、函数参数传递的三种不同方式
5.1、值传递
eg:
void Exchg1(int x, int y) /* 定义中的x,y变量被称为Exchg1 函数的形式参数*/ { int tmp; tmp = x; x = y; y = tmp; printf("x = %d, y = %d. ", x, y); } main() { int a = 4,b = 6; Exchg1(a, b); /*a,b变量为Exchg1函数的实际参数。*/ printf("a = %d, b = %d. ”, a, b); return(0); }
上述代码的运行结果是:
x=6,y=4
a=4,b=6
函数Exchg1在被调用时只是把实参a,b的值传递给了形参x,y,而在函数Exchg1内对变量a,b本身没有进行别的任何操作,在该函数体内操作的只是变量x,y,故在变量a,b内存储的值还是没有发生改变。以上这种函数参数传递方式叫作值传递方式。
5.2、地址传递方式
1 void Exchg1(int *x, int *y) /* 定义中的x,y变量被称为Exchg1 2 函数的形式参数*/ 3 { 4 int tmp; 5 tmp = *x; 6 *x = *y; 7 *y = tmp; 8 printf("*x = %d, *y = %d. ", *x, *y); 9 } 10 11 12 main() 13 { 14 int a = 4,b = 6; 15 Exchg1(&a, &b); /*a,b变量为Exchg1函数的实际参数。*/ 16 printf("a = %d, b = %d. ”, a, b); 17 return(0); 18 }
上述代码的运行结果是:
*x=6,*y=4
a=6,b=4
函数Exchg1的入口参数是两个指向整型变量的指针,在该函数体内,这两个指针所指向的内存单元的值被交换。于是乎在主函数中调用该函数时,传递给该函数的是变量a,b在内存单元中的地址,而该函数执行的操作正是将这两个单元地址里面的值进行交换,故该函数运行结束之后a,b的值已经进行了交换。这种函数参数的传递方式叫作地址传递方式。
5.3、引用传递方式
1 void Exchg3(int &x, int &y) /* 注意定义处的形式参数的格式与 2 值传递不同*/ 3 { 4 int tmp = x; 5 27 6 x = y; 7 y = tmp; 8 printf("x = %d, y = %d. ", x, y); 9 } 10 main() 11 { 12 int a = 4; 13 int b = 6; 14 Exchg3(a, b); /*注意:这里调用方式与值传递一样*/ 15 printf("a = %d, b = %d. ”, a, b); 16 }
这种函数参数传递方式叫作引用传递方式,为什么叫作引用传递方式呢?因为在形参x、y前都有一个取地址符号“&”。有了这个,调用Exchg3时函数会将a、b 分别代替了x、y了,我们称:x、y分别引用了a、b变量。这样函数里头操作的其实就是实参a、b本身了,也就是说函数里是可以直接修改到a、b的值了。
6、最后的一点补充:
6.1:如果指针变量p已指向数组中的一个元素,则p+1指向的是同一数组中的下一个元素,p-1指向的是同一数组中的上一个元素。
caution:执行p+1时并不是将p的值简单地加1,而是加上一个数组元素所占用的字节数
6.2:在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长