C语言(四)

指针进阶
摘要由CSDN通过智能技术生成

目录

指针进阶

指针概念

字符指针和字符串指针

指针数组

数组指针

数组名是首元素地址;

数组和指针的一些举例区分

传递数组的正确方式

函数指针

函数指针的应用

函数指针数组指针

回调函数

指针练习

指针题

指针联系2

指针笔试题:


指针进阶

指针概念

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)一样。

经过编译器验证,甚至在声明函数指针的时候,也可以不带 * 。

结论:函数指针中的*是个摆设ÿ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值