目录
指针进阶
指针概念
1,指针就是变量,用来存放地址,地址为一标识一块内存空间
2,指针的大小是固定的4/8个字节(32位平台/64位地址平台)
3,指针式有类型的,指针的类型决定了指针的+—整形的步长,指针解引用时候操作的权限
4,指针的运算
字符指针和字符串指针
字符指针
char ch = 'c';
char *pc = &ch;
字符串指针
char* pc ="hello world";
可以把字符串看作一个含有‘\0’字符的字符数组,那么其实字符串指针是一种特殊的数组指针。
来看一个例子
char str1[] = "hello";
char str2[] = "hello";
char* str3 = "hello";
char* str4 = "hello";
判断str1和str2,str3和str4分别是否相等。
int main()
{
char str1[] = "hello";
char str2[] = "hello";
char* str3 = "hello";
char* str4 = "hello";
if (str1 == str2)
printf("str1==str2");
else
printf("str1!==str2");
if (str3 == str4)
printf("str3==str4");
else
printf("str3!==str4");
return 0;
}
输出:结果来看,str1和str2不相等,str3和str4相等
str1!==str2
str3==str4
原因:str1和str2是分别定义了一个数组,给他们赋值为”hello",所以不想等。
str3和str4是定义指针,指向同一个常量字符串,这个字符串储存在内存中,有自己的地址,指针都指向这个地址,str3和str4自然是相等的.
注意:常量字符串对应的指针不能被修改
char* arr = "hello"; 这种常量字符串不能被修改而且地址固定
指针数组
存放指针的数组
int* arr1[10]; 整形指针数组
char* arr2[4]; 一级字符指针的数组
char** arr3[5]; 二级字符指针的数组
数组指针
数组指针 -- 一个指针,指向数组的指针
比如:
整形指针--是一种指向整形的指针
字符指针--是一种指向字符的指针
定义数组指针的方式
int arr[10] = { 0 };
int (*p)[10] = &arr;
如果不加括号,p会先和【 】结合,会被编译器认为是指针数组。
所以要加括号,保证定义的是指针。
举例:
double* d[5];
double * (*pd) [ 5 ] = &d ; double*--表示指针指向的数组的元素类型是double*;
(*pd)---表示这是一个指针
[5]---表示这是一个数组指针
pd表示一个指针数组指针,这是一个指针,指向一个含有五个元素的数组,数组元素类型为double指针。
数组名是首元素地址;
但是有两个意外:
1,sizeof(数组名) -- 数组名表示整个数组,计算的是整个数组的大小,单位是字节
2,&数组名 -- 数组名表示整个数组,取的是整个数组的地址
数组和指针的一些举例区分
int arr[5]; 整形数组
int* arr[5]; 指针数组
int(*arr)[5]; 数组指针
int(*parr[10])[5]; 数组指针数组
parr是一个存储数组指针的数组
该数组能够存放10个数组指针
每个数组指针指向一个数组,数组5个元素,每个元素是int类型
传递数组的正确方式
一维数组传参
void test(int arr[]) {}
void test(int arr[10]) {}
void test(int *arr) {}
一维(指针)数组传参
void test2(int *arr2[20]) {}
void test2(int **arr2) {}
二维数组传参
void test(int arr[3][5]) {}
void test(int arr[][5]) {}
void test(int (*arr)[5]) {}
二级指针可以传的参数:1,二级指针;2,一级指针的地址;3,一级指针数组名(一级指针数组的首元素地址)
指针
一级指针:
int *p 整形指针
char *ch 字符指针
void *vp 无具体类型指针
二级指针:
char **p;
int **p;
数组指针:指向数组的指针
int(*p)[4];
数组
一维数组;
二维数组
指针数组;
函数指针
函数指针
指向函数的指针:存放函数地址的指针
直接上结论:函数名就是函数地址,就是函数指针
数组名 != &数组名
函数名 == &函数名
举例:
int add(int a, int b)
{
return a + b;
}
int main()
{
printf("%p\n", &add);
printf("%p\n", add);
int (*pf)(int,int) = &add; //pf是一个函数值指针变量
//第一个int表示返回类型; (*pf)表示指针 ;(int ,int)表示参数
//这样一个函数指针就创建完成了
return 0;
}
//输出
005B1023
005B1023
很明显:函数名就是函数地址;
根据上面推理:
pf == &add 而且 &add == add; *pf == add;
可推:pf == *pf;
所以,在函数指针中,*pf与pf是完全相等的,*在函数指针这里可带可不带,带上只是为了便于理解。
即:pf(1,2)与add(1,2)一样。
经过编译器验证,甚至在声明函数指针的时候,也可以不带 * 。
结论:函数指针中的*是个摆设ÿ