C语言指针
1、指针定义
指针是一个变量, 它保存的是另一个变量的地址, 即内存位置的直接地址。
int ptr; //整型变量,ptr+1 表示变量值+1;
const int ptr;//只读变量,和int const ptr效果一致;
int *ptr1; //定义一个整型指针, ptr+1 表示地址偏移 int 类型字节;
int ptr[3];//3 个成员的整型数组, ptr+1 表示指向 ptr[1]的地址;
int *ptr[3];//指针数组,ptr[3]是数组,int*再与 ptr[3]结合成指针数组, 表明数组中保存着 int 类型的指针, ptr+1 表示指向 ptr[1][]的地址, 即二维数组 ptr[1][0]的地址;
int (*ptr)[3];//数组指针,()优先级高,(*ptr)是指针, 再与[3]结合, 说明指针所指向的内容是数组, 最后和 int 结合, 表示数组元素类型是 int 类型。ptr+1 表示指向 ptr[1][]的地址, 即 ptr[1][]的地址;
int **ptr;//二维指针变量, 保存一维指针变量的地址;
int const *ptr;//常量指针,ptr指向的内容不可以修改,但可以改变指向;
int *const ptr;//指针常量,ptr的指向不可以修改,但可以修改指向的内容;
2、*p++、 *(p++)、 *++p、 ++*p、 *p+1、 *(p+1)
#include <stdio.h>
int main()
{
int buff[]={10,20,30};
int *p=buff;
/*1 buff[0]的地址:&buff[0]*/
printf("print1 buff addr:%#x\n",buff);
/*2 buff[0]的地址:&buff[0]*/
printf("print2 p addr:%#x\n",p);
/*3 偏移 sizeof(int)字节*/
printf("print3 p+1 addr:%#x\n",p+1);
/*4 取 buff[0]的值*/
printf("print4 *p=%d\n",*p);
/*5 取 buff[0]的值+1*/
printf("print5 *p+1=%d\n",*p+1);
/*6 地址偏移 sizeof(int)再取值, 即 buff[1]*/
printf("print6 *(p+1)=%d\n",*(p+1));
/*7 先取*p 的值,再 p+1*/
printf("print7 *p++=%d\n",*p++);
/*8 先取*p 的值, 再(*p)+1*/
printf("print8 ++*p=%d\n",++*p);
/*9 先 p+1,再取*(p+1)*/
printf("print9 *++p=%d\n",*++p);
}
运行结果:
[xsw@xsw cc]$ ./a.out
print1 buff addr:0xbf98f2a0
print2 p addr:0xbf98f2a0
print3 p+1 addr:0xbf98f2a4
print4 *p=10
print5 *p+1=11
print6 *(p+1)=20
print7 *p++=10
print8 ++*p=21
print9 *++p=30
3.NULL指针和void*指针
NULL 是标准宏定义, 用来表示空指针常量, 在声明指针变量时若没有确切地址赋值, 可以给指针变量赋 NULL。
#include <stdio.h>
int main()
{
char *ptr=NULL;
printf("ptr addr:%d\n",ptr);
return 0;
}
执行结果
[xsw@xsw cc]$ ./a.out
ptr addr:0
在大多数操作系统中程序不允许访问地址为 0 的内存, 因为该内存是操作系统保留的。 指针指向地址为 0 的内存表示该指针指向的地址不可访问。 按照惯例 NULL 指针假定为不指向任何东西。
void 表示”无类型”, void*指针表示”无类型指针”, 即可指向任何数据类型。
#include <stdio.h>
int main()
{
void *p;
int a=100;
char buff[]={0,10,20,30};
p=&a;//保存 int 型变量地址
//void*指针访取值时要保证和所指向的变量类型一致
printf("*p=%d\n",*((int *)p));//强制转换成 int*
p=buff;//指向字符数组首地址
//强制转换成 char*
printf("*p=%d\n",*(char *)p);//buff[0]
printf("*(p+1)=%d\n",*(char *)(p+1));//地址往后偏移 char 字节: buff[1]
printf("*p+1=%d\n",*(char *)p+1);//取出的值+1: buff[0]+1
return 0;
}
执行结果
*p=100
*p=0
*(p+1)=10
*p+1=1
注:void 几乎只能用于指针的声明和函数返回值以及函数形参, 不能用于变量的定义。
4、二维指针
二维指针:指向指针的指针。 保存一维指针的地址。
指针声明:int **ptr;
#include <stdio.h>
int main()
{
int a=0x12;
int *ptr=&a;//一维指针保存变量地址
int **pptr=&ptr;//二维指针保存一维指针本身地址
//1 ptr==&a
printf("line1:a addr:%#x\n",ptr);
//2 *(&ptr)==&a
printf("line2:*(&ptr)=%#x\n",*(&ptr));
//3 pptr==&ptr
printf("line3:pptr :%#x\n",pptr);
//4 *ptr==*(&a)==a
printf("line4:*ptr=%#x\n",*ptr);
//5 *(&ptr)==ptr==&a
printf("line5:*pptr=%#x\n",*pptr);
//6 **pptr==**(&ptr)==*ptr=*(&a)
printf("line6:**pptr=%#x\n",**pptr);
//7 ***(&pptr)==**(&ptr)==*ptr==*(&num)=0x12
printf("line7:**pptr=%#x\n",***(&pptr));
}
执行结果:
[xsw@xsw cc]$ ./a.out
line1:a addr:0xbf90384c
line2:*(&ptr)=0xbf90384c
line3:pptr :0xbf903848
line4:*ptr=0x12
line5:*pptr=0xbf90384c
line6:**pptr=0x12
line7:**pptr=0x12
5、数组指针
指针定义:int (p)[n];指向数组整体的指针。 数组指针类型:int ()[n];
()优先级高, 所以 p 是一个指针, 指向一个整型的一维数组, 一维数组的成员个数位 n, 也就是说 p 的步长为 n。 即 p+1 偏移的地址为 n 个 int 型长度。 因此数组指针也称为行指针。
优先级: () > [] > *
示例一:数组指针指向一维数组示例
#include <stdio.h>
int main()
{
int buff[]={11,22,33,44,55,66};
int (*ptr)[6];//数组指针,指向数组整体
ptr=&buff;
int i;
//数组指针 ptr+1 偏移指向的数组整体大小,即偏移 6*sizeof(int)=24 字节
printf("ptr addr:%#x\n",ptr);
printf("(ptr+1) addr:%#x\n",ptr+1);
/*数组指针遍历 buff*/
for(i=0;i<6;i++)
{
printf("%d ",*(*ptr+i));//或*(ptr[0]+i)或 ptr[0][i]
}
printf("\n");
return 0;
}
执行结果:
[root@xsw cc]# ./a.out
ptr addr:0xbfbc8ce0
(ptr+1) addr:0xbfbc8cf8
11 22 33 44 55 66
示例二:数组指针指向二维数组示例:
#include <stdio.h>
int main()
{
int buff[][3]={1,10,3,4,5,6};//每行有 3 个元素
int (*p)[3]=buff;
printf("*p[0]=%d\n",*p[0]);//等价于 buff[0][0]
printf("*(p[0]+1)=%d\n",*(p[0]+1));//等价于 buff[0][1]
printf("*p[1]=%d\n",*p[1]);//等价于 buff[1][0]
}
6、指针数组
定义:int p[n];数组中保存 int指针。指针数组类型:int *[n], p的类型是 int **,p+1 偏移的地址为:sizeof(int *)。
示例一:将一维数组赋值给指针数组
#include <stdio.h>
int main()
{
int buff[]={11,22,33,44,55,66};
/*
//初始化直接赋值
int *ptr[10]={&buff[0],&buff[1],&buff[2],&buff[3],&buff[4],&buff[4]}
*/
int *ptr[10];//指针数组,数组中保存 int 型指针
/*数组指针赋值*/
int i;
for(i=0;i<6;i++)
{
*(ptr+i)=&buff[i];//或:buff+i
}
for(i=0;i<6;i++)
{
printf("%d ",*(*ptr+i));
}
printf("\n");
return 0;
}
运行结果:
[root@xsw cc]# ./a.out
11 22 33 44 55 66
示例二:将二维数组赋值给指针数组示例
#include <stdio.h>
void tow_array(int (*buff)[3],int line);
int main()
{
int buff[][3]={1,10,3,4,5,6};//每行有 3 个元素
int *p[3];
*p=buff[0];
p[0]=buff[0];
*(p+1)=buff[1];
printf("%d\n",(*p)[0]);//等价于:p[0][0]
printf("%d\n",(*p)[1]);//等价于 p[0][1]
printf("%d\n",*(p[0]+1));//等价于 p[0][1]printf("%d\n",*(p+1)[0]);//等价于 p[1][0], *(p+1)指向 buff[1][0]地址
printf("%d\n",*(*(p+1)+1));//等价于 p[1][1]
}
printf("%d\n",*(p+1)[0]);//等价于 p[1][0], *(p+1)指向 buff[1][0]地址
printf("%d\n",*(*(p+1)+1));//等价于 p[1][1]
注:二维数组赋值给指针数组时 p=buff 是错误的。
7、函数指针
函数指针:指向函数的指针变量。 本质是指针变量。
#include <stdio.h>
int func(int a,int b);
int main()
{
//pfunc 表示函数指针变量
int (*pfunc)(int ,int );//定义函数指针,可以在定义时初始化
pfunc=func;//初始化函数指针,也可写成 pfunc=&func
int data=pfunc(10,20);
printf("%d\n",data);
}
int func(int a,int b)
{
return a+b;
}
执行结果:
[xsw@xsw cc]$ ./a.out
30
注:定义函数指针时必须保证和所指向的函数形参返回值一致
8、回调函数
#include <stdio.h>
int func_1(int a,int b);
int func_2(int a,int b);
int func_3(int a,int b);
void func_Callback(int a,int b,int (*pfunc[])(int,int),int num);
int main()
{
int data;
int i=0;
//定义函数指针数组
int (*pfunc[3])(int ,int)={func_1,func_2,func_3};
func_Callback(30,20,pfunc,sizeof(pfunc)/sizeof(int *));
}
int func_1(int a,int b)
{
printf("\t[%s] %s line:%d %d+%d=%d\n",__FILE__,
__FUNCTION__,
__LINE__,
a,b,a+b
);
return a+b;
}
int func_2(int a,int b)
{
printf("\t[%s] %s line:%d %d*%d=%d\n",__FILE__,
__FUNCTION__,
__LINE__,
a,b,a*b
);
return a*b;
}
int func_3(int a,int b)
{
printf("\t[%s] %s line:%d %d%%%d=%d\n",__FILE__,
__FUNCTION__,
__LINE__,
a,b,a%b
);
return a%b;
}
/***************************回调函数******************
**
**
**形参:int a,int b ---函数指针所需要动形参
** int (*pfunc[])(int,int) --- 函数指针数组
** int num ---函数指针数组成员个数
**
*********************************************************/
void func_Callback(int a,int b,int (*pfunc[])(int,int),int num)
{
int i;
int data;
for(i=0;i<num;i++)
{
data=pfunc[i](a,b);
printf("data=%d\n",data);
}
}
执行结果:
[xsw@xsw cc]$ ./a.out
[func.c] func_1 line:17 30+20=50
data=50
[func.c] func_2 line:22 30*20=600
data=600
[func.c] func_3 line:27 30%20=10
data=10