现在来复习一下指针,尽管那本C语言的书都看了很多遍了…
1、 变量的指针和指向变量的指针
int i=10, j=20 ;
int *p1, *p2 ;
p1 = &i;
p2 = &j;
//这里特别要注意,p1和p2保存的是变量的地址!如果写成了
p1= i;
P2=j;
就错了,因为,不能把一个整型变量赋给一个指针,这样做相当危险,这样做的结果是,让p1指向地址为10的内存单元,万一这个单元恰好是系统所使用的资源,在以后通过p1去访问这个单元,修改,或者释放等操作,都会给系统带来毁灭性的灾难!
可以在定义指针的时候就给他确定指向
int i= 10 ;
int *p = &i; //这样也行。
2、 数组与指针
#include<stdio.h>
#include<string.h>
void main(){
int *p ;
int a[10] = {0} ;
p= a ;
printf("%d\n",a) ;
printf("%d\n",p) ;
printf("%d\n",&a) ;
}
经测试他们的输出是一样的值,1244956由此可以看出,对于数组名a来说,a和&a都是这个数组的首地址!
a是地址常量,不可以改变的。他不像指针p那样可以随意地自加。
假设 p指向的是整型的一维数组a,那么*p++是啥意思呢?
答:因为*和 ++的优先级是相等的,那么根据自右向左的结合原则,*p++就相当于*(p++)作用是先得到p指向的值,然后使p自加。
请问:----------à *p++ 和 *(++p)的区别?
很明显,*p++就相当于*(p++)意思是先的到p所指向的值,然后使p自加
*(++p) 意思是得到p所指的下一个单元空间里的值。
这里要牢牢记住,*和++的运算优先级是相等的,要采用从右向左的结合规则!当用小括号把他们分开后,其含义便迎刃而解!
3、 多维数组与指针
这里有取二维数组吧。
int a[3][3]
*a相当于 *(a+0)即a[0]
这里要说明的似乎有很多,这也是数组与指针中的难点,用的时候要千万小心。
int a[4] 与 int (*p)[4]的区别?
他们的作用都是声明一个能存放4个整型数据的数组。
那么,int *p[4]呢?
他就是指针数组了,有4个指向int型变量的指针。
4、 字符串与指针
关于对使用字符串指针变量和字符数组的讨论
初始化中可能会遇到的问题:
数组名与指针的区别:
char str[] ;
str = “I love china”;
!!!!!这是不对的,因为”I love china”返回的是一个地址,这个地址不能用str来接受,str是不能改变的地址。
Char *p ;
p = “I love china” ; 等价于 char *p = “I love china”
!!!!这就是对的。指针可以接受这个地址。
那么怎样对数组初始化呢?瞧!
char str[] = {“I love china”} ; 或者 char str[] = “I love china” ;
在需要用户来对一个字符数组进行初始化时,千万要注意,一定要限定用户的输入,不然就会导致内存溢出!看下面的例子。
正确的做法。
char str[10] ;
scanf(“%s”,str); // 这样系统就只能截取最多10个字符,准确地说是最多9个!因为第十位字符是’\0’
错误的做法:
char *p ;
scanf(“%s”,p); //这是错误的做法,因为没有限定用户的输入长度限制,当恶意用户把输入指定为一个很大的文件时,系统且不崩溃?!!那才真的叫内存耗尽啊!
5、 指向函数的指针
比如求两个数的最大者。
#include<stdio.h>
#include<string.h>
void main(){
int max(int , int );//声明有一个max函数
//int max(int x, int y);这是错误的,不能指定x,y
int (*p)(int , int); //声明一个指向返回值是int型,有两个int参数的函数
int a, b, c ;
a = 10;
b = 20;
p=max;
c= p(a,b);
printf("%d\n",c);
}
int max(int x, int y){
return x>y? x:y ;
}
这里要强调的是,定义的指向函数的指针是指向一类函数的指针,在linux系统内核中,这样的指针很多。这里不得不感叹一下,linux里面的函数名,有些还是比较难懂的。