目录
一、字符指针
1.const作用简单介绍
二、指针数组、数组指针
1.指针数组
2.数组指针
3.数组指针的使用
3.1数组指针传参
四、数组传参
4.1一维数组传参
4.2二维数组传参
五、函数指针
5.1函数指针存储
5.2函数指针调用
5.3练习
指针就是一个变量,用来存放地址,一个地址唯一标识一块内存空间。
指针大小4/8字节(32位平台/64位平台)
指针是有类型的,其类型决定了指针±整数时的步长,和对其解引用‘*’时的权限(能够操作几个字节)
char arr='d';
char*p=&arr;(取出arr地址放入到p中)
此时*p=='d';
*p='w';(把对应地址存放变量d赋值为w)
其余类型指针情况类似
一个特殊情况
int main()
{
char *str="hello world";
printf("%s\n",str);
return 0;
}
此时打印的结果是hello world,是把hello world放入到str指针变量里了吗?显然不是
"hello world"为常量字符串,本质是把字符串的首地址放入到了str中。
一个练习
#include
int main()
{
char s1[] = "hello";
char s2[] = "hello";
const char *s3 = "hello";
const char *s4 = "hello";
if(s1 ==s2)
printf("s1等于s2\n");
else
printf("s1不等于s2\n");
if(s3 ==s4)
printf("s3等于s4\n");
else
printf("s3不等于s4\n");
return 0;
}
结果为s1不等于s2
s3等于s4
原因是s3和s4指向的是同一个常量字符串,C/C++会把常量字符串存储单独存储到一个内存区域,当几个指针指向同一个字符串时,实际上会指向同一内存。但是用相同的常量字符串初始化不同数组时就会开辟不同的内存块。
const修饰的常变量(本质还是变量)不能用于arr[中];
const在*同一侧时起的作用都是相同的
const char*p;char const*p,此时*p不能赋值改变
char* const p,此时p不能被赋值改变
用于存放指针的数组
int *arr[5];//存放五个int类型的指针数组
int **arr[5];(二级指针)//存放五个指针指向int*的数组
数组名表示的是数组首元素地址,以下两种情况除外
此时&arr为取出整个数组地址,(但是&arr==arr);sizeof(arr)中的arr为整个数组字节大小
指向数组的指针,用于存放整个数组的地址
int(*p)[5];//p为指针,指向含有五个元素的整型数组。
int*p[5];
[]的优先级高于*,如果不加(),p会和[5]先结合成一个有五个元素的数组
下面举个例子进行练习
#include
int main()
{
int arr[10] = { 0 };
printf("arr = %p\n", arr);
printf("&arr= %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1= %p\n", &arr+1);
return 0;
}
可以看到arr和&arr的输出是相同的,但是当二者都加1后结果却不相同了,原因就在于,&arr取出的是整个数组地址,加1后跳过的是整个数组
#include
int main()
{
int arr[5]={1,2,5,4,7};
int(*p)[5]=&arr;
return 0;
}
二维数组传参是传的是第一行元素的地址,行数可以不设置,但列一定要设置
#include
void arr1(int arr[][4], int row, int col)
{
int i = 0;
for(i=0; i|
在我们了解以上知识后我们来看看这个int(*arr[8])[6]
对其进行分析arr和[8]相结合,组成一个数组,有8个元素,每个元素为指针类型,指针指向含有6个int型元素的数组,每个元素类型为int(*)[6],存放数组指针的数组。
一维数组传参传的是首元素地址,数组存放是连续的
#include
void test(int arr[])//F or T?
{}
void test1(int arr[10])//F or T?[]中的数字没有意义,仅仅是为了方便初学者学习理解,并不会创建一个形参数组
{}
void test2(int *arr)//F or T?
{}
void test3(int *arr[20])//F or T?
{}
void test4(int **arr)//F or T?
{}
int main()
{
int arr[10] = {0};
int *arr2[20]={0};//传地址二级指针(地址的地址),每个元素为int*类型
test(arr);
test1(arr);
test2(arr);
test3(arr2);
test4(arr2);
}
答案:T T T F T
二维数组传的是第一行元素的地址,二维数组本质上也是连续存放的,第一行后面跟着第二行。。。。。
void test(int arr[3][5])// T
{}
void test(int arr[][])// F
{}
void test(int arr[][5])// T 行可以省略,列不能省略
{}
//二维数组传参,函数形参的设计只能省略第一个[]的数字。
void test(int *arr)// F
{}
void test(int* arr[5])// F 是指针数组
{}
void test(int (*arr)[5])// T 数组指针
{}
void test(int **arr)// F 二级指针
{}
int main()
{
int arr[3][5] = {0};
test(arr);
}
#include
void test()
{
printf("C++\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);//和数组不同,这两种都是函数地址
return 0;
}
int Add(int x,int y)
{
return 0;
}
函数返回类型为int,其参数为两个int元素,int (*pp) (int,int)=Add;pp就是函数指针变量
pp中存放的是Add地址,进行调用对其解引用*即可,(*pp)(num1,num2);
注意不要写成*pp(num1,num2)这种形式
但其实不对其解引用直接pp(num1,num2);也可以正常使用。*在此处并没有意义
写成*pp(1,2)这种形式就变成了*3,就会出现问题。
//码1
(*(void (*)())0)();
//码2
void (*evial(int , void(*)(int)))(int);
这两串代码是什么意思?
例1
例2
void ( *eva( int , void(*)(int) ) )(int);
void(*)(int)和int为eva( , )的两个参数的类型
eva的返回值类型为void(*)(int)
其形式比较复杂,我们可以通过typedef对其函数指针类型进行重命名
typedef void(*pp)(int)//将函数指针类型void(*)(int)重命名为pp
typedef void(*)(int) pp;//这种形式是错误的
pp eva(int,pp)
后续会更新函数指针数组,指向函数指针数组的指针和回调函数qsort模拟实现。
感谢各位的阅读。