首先需要说明的是指针的概念:
- 指针变量是用来储存地址的变量,地址唯一标识一块内存空间
- 指针的大小固定为4个或8个字节(32位/64位)
- 存在不同的指针类型,其决定了指针的步长
- 指针相减得到的是元素个数
1.字符指针
字符指针是存放字符地址的指针
定义方法:
1.直接定义一个指针变量指向一个字符: char*pc='c',此时指针储存的是该字符的地址
2.定义指针变量指向字符串常量:const char* pc='abcdef'此时指针储存的是字符串首元素的地址,
const char*表示pc指向的元素不能被修改
下面用一段代码说明字符串常量与字符的区别
#include<stdio.h>
int main()
{
char str1[] = "hello world";
char str2[] = "hello world";
if (str1 == str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
const char* str3 = "hello world";
const char* str4 = "hello world";
if (str3 == str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
运行结果如下:
原因是常量字符串无法被修改,故被多次使用时,不会再创建新的字符串,故指针str3与str4
指向相同的字符串,两者相同
2.指针数组
指针数组是存放指针的数组
定义方法:
//存放字符指针的数组
char* a[4]={"abc","def","hij","klm"};
//存放整型指针的数组
int b1[]={1,2,3};
int b2[]={4,5,6};
int b3[]={7,8,9};
int* pb[3]={b1,b2,b3};
3.数组指针
数组指针是存放数组地址的指针
定义方法:
int a[10];
int (*pa)[10]=&a;
在前面的学习中,我们知道了数组名代表的是数组首元素的地址,而指针类型的不同又影响了其步长,下面用一段代码说明 array与&array 的区别
#include<stdio.h>
int main()
{
int array[4] = { 1,2,3,4 };
printf("%p\n", array);
printf("%p\n", array+1);
printf("\n");
printf("%p\n", &array[0]);
printf("%p\n", &array[0]+1);
printf("\n");
printf("%p\n", &array);
printf("%p\n", &array + 1);
printf("\n");
}
打印结果如下
可以看出,array,array[0],&array的地址相同,但array+1加的是4个字节,即跳过了一个int类型的变量,&array+1加的是16个字节,即跳过了整个数组
二维数组传参:
void test ( int (*a)[5] )
{}
int main()
{
int a[3][5]={0};
test(a);
}
4.函数指针
函数指针是存放函数地址的指针
定义方法:
int add(int x,int y)
{
return x+y;
}
int main()
{
int (*pf)(int ,int )=&add;
return 0;
}
关于函数指针的两段代码
int main()
{
(*void (*)())0();
return 0;
}
代码先将0强制类型转换为void(*)()类型的函数指针,然后调用,即调用0地址处的函数
int main()
{
void (* signal(int ,void(*)(int) ) )(int);
return 0;
}
这段代码是函数声明,声明的函数名为signal,signal函数的参数有2个,第一个是int类型,第二个是函数指针类型,该函数指针指向的函数的接收参数为int,返回类型为void.signal函数的返回类型是一个函数指针,该函数指针指向的函数的接收参数为int,返回类型为void。
这段代码可以进行如下简化
typedef void(*pf_t)(int);
pf_t signal(int ,pf_t);