1.指针基础
1.1指针基础
a.指针记录某数据的地址及类型,常简称地址。用一个变量储存指针,即指针变量。
指针变量数据类型含int,float,double,char等。
定义指针变量 : 类型 *变量名 ,
可一并初始化。
int a=1;
int *pointer=&a;
printf("%d",*pointer);//引用目标变量值
printf("%o",pointer);//引用指针值(八进制)
b.要输出目标变量值时,在指针变量前加*。&为取址运算符,作用与*相反。
c.指针变量与指向数据类型一般需一致,否则,部分编译器将后者自动转换为前者的数据类型。
d.指针数值加减时,实际变化字节数为输入的数值乘以其数据类型所占字节数。在数组中,常用p++,p–,p1-p2等形式改变指向的元素。
1.2野指针
野指针指记录的地址不确定或确定但内部内容随机,不可知的指针。
如果内部地址为某些重要内存空间,在程序中无意间被野指针引用并修改,可能引起程序甚至系统崩溃。我们应当避免产生野指针。具体方法为:
a.指针变量定义后及时初始化;
b.指针指向数组元素时,注意元素下标不越界,尤其使用自增,自减运算符;
c.若需定义指针留作备用,因系统仍会分配其值,可赋值为NULL,表示空地址。
2.指针与数组
2.1基础
系统将数组名作指针处理,指向数组首元素,如定义a[10],则a为a[0]地址。
定义数组后对数组名一般不会改变其值,可定义与数组名相等的指针变量,对该变量值作处理。
char a[10];
int *p=&a[O];//或int*p=a
1.p=a[0]时,a[i]=*(p+i),&a[i]=p+i.
2.指针变量p1,p2指向同一数组元素时,可用p2-p1求得距离(所隔元素数), 但p1+p2不合法;
3.结合性上,*p++等价于 *(p++)和a[i++].
2.2指针与多维数组
以下举一例:
int a[3][4];//定义二维数组;
a.二维数组名为二维数组首元素,a=&a[0];
而其中又有a[0]=&a[0][0],三者记录的地址实际相等,但意义不同。等价关系如下:
a//二维数组名,为a[0]持针,指向0行
a[0],*(a+0),*a//a[0][0]指针,指向0行0列
a+l,&a[l]//a[1]指,指向1行
a[1],*(a+1)/a[1][0]指针,指向1行0行
a[1]+2,*(a+1)+2,&a[l][2]// a[1][2]指针,1行2列
*(a[1]+2),*(*(aH)+2)) a[1][2]/元素值
b. 定义指向n个整型元素组成的一维数组的指针变量pt:
int (*pt)[n];//n为正整数且不可省略
常作为函数形参接收二维数组名实参。
3.指针与字符串
a.字符串在系统中作为字符数组处理,故字符串名也作为指针指向首元素(首字符)。
b.定义字符指针变量,
char str[50]="I learn c now.";
char *p=str;
//或者更简洁:
char *p="I learn c now.";
此时,str[7]=*(p+7);
c.用strcpy将字符串str2内容复制到str1时,str2末尾一般要赋值为占位符“/0”,否则str1中剩余内容仍保留(str1长度更大)。若str1直至末尾都有赋值且不为占位符,则输出str1时会出bug。
4.指针与函数
a.函数名实际指向函数起始地址.可利用函数指针调用函数。
演示如下:
int max(int,int);
int (*p)(int,int);//定义函数指针
p=max;//初始化为max
int a,b,c;
c=max(a,b);//等价于:
c=(*p)(a,b);
b.可定义一指针变量等于函数名,通过令指针变量先后指向同数据类型的不同函数,实现一个调用式调用不同函数。
c.指针变量常作函数参数,在不同函数传递地址,以此处理其指向的数据,可绕过局部变量的限制。
5.其他
a.void类型指针为空类型,NULL为空地址,其值为0;
b.用malloc(unsigned int)申请开辟临时空间,进行动态内存分配;
其他有如calloc,realloc等,最终用free释放内存。
c.C99中,malloc返回值为void型,需进行转换,一些编译器会自动转换。