C语言第16讲
typedef作用:将莫个类型重新命名int main()// 1int a = 10;// %d 打印整形(int)// 打印 10 10;return 0;指针类型的更改方式为:写出类型,在 * 后写入新名字例2:数组指针int main()// 1.// 2.// 两地址相同return 0;例3:函数指针int main()// 1.// 2.\\ 两者打印一样return 0;
字符指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char ch[] = "holle world"; // 在栈上创建一个字符数组并初始化
char* pc1 = ch; // pc1指向这个数组
*pc1 = 'w'; // 正确:修改数组的第一个字符为'w'
printf("1 %s\n", pc1); // 输出:"wolle world"(注意原字符串是"holle")
char* pc2 = "holle world"; // 这串代码在执行时创建了个常量字符串“holle world”
// 将常量字符串的首个元素地址存入pc2中
printf("2 %s\n", pc2);
*pc2 = 'w'; // 这里不能更改 常量 字符串
printf("3 %s\n", pc2); // 导致这里不会执行
return 0;
}
运行:
数组指针变量
(谁在后方谁是名词)数组指针变量 = 指针变量
整形指针:int* 指向整形的指针
字符指针:char* 指向字符的指针
数组指针: 指向数组的指针
需要整个数组的地址
int* p1[10]; p1是数组,存放指针
int (*p2)[10]; p2是指针,存放数组的地址
因为 [ ] 优先级高于 *
所以 (*name)是指针
name[ ]是数组
数组指针的类型
由上 int (*p2)[10] 为数组指针,其类型便是将名称去除剩下的
int (*)[10]
二维数组传参的本质
数组名是首元素地址
//二维数组的首元素是 第一个一维数组
int arr[3][3] = {{1,2,3},{2,3,4},{3,4,5}};
函数形参可以写成:int arr[ ][ 3 ];
但本质是数组指针:int* (*p)[ 3 ];
例如将一维数组传参过去: 二维数组
1.传参为指针 (*p) // 传参为指针 (*p)
2.指向类型是 int // 指向类型是 int [ 3 ]
3.int(*p); = int* p; // int (*p)[ 3 ];
函数指针变量
(谁在后方谁是名词)函数指针变量 = 指针变量
函数指针:指向函数的指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int(*p)(int, int) = Add;
return 0;
}
我们在学习数组时:数组名是首元素地址
函数和数组不同:&fun 和 fun都是整个函数的地址
函数类型
与数组类似,除去名称剩下的为类型
以 int Add(int x, int y);为例
int (int x, int y);为类型
但参数中的名称也常常省略
int (int x, int y); = int (int x, int y);
函数指针使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
int(*p)(int, int) = Add;
int z1 = Add(2, 3);
int z2 = (*p)(2, 3); // 通过 p 的地址解引用到Add函数
int z3 = p(2, 3); // 通常可以省略(*),直接使用p,因为p和Add都为函数地址开头
printf("%d %d %d",z1,z2,z3);
return 0;
}
运行:
两段有趣的代码
代码1:
(*(void (*)())0)();
0为地址: 0x0000000
void(*)(): 为类型
( void(*)() ) 0: 在0x00000000处存入函数类型为 void(*)() 的地址
*( void(*)() ) 0: 解引用0x00000000处存入的地址,找到存入的函数
( *(void (*)() )0 ) (): 进行传参
代码2:
void (*signal(int , void(*)(int)))(int);
这为函数声明:
分开:void (*)(int); signal(int , void(*)(int))
返回类型: void (*)(int);
函数名: signal
函数具有两个参数类型: (int , void(*)(int))
typedef:类型重定义
typedef作用:将莫个类型重新命名
例1:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
// 1
int a = 10;
//2
typedef int i;
i b = 10;
printf("%d %d", a, b); // %d 打印整形(int)
// 打印 10 10;
return 0;
}
指针类型的更改方式为:
写出类型,在 * 后写入新名字
例2:数组指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int arr[5] = { 0 };
// 1.
int(*parr1)[5] = &arr;
// 2.
typedef int(*p_arr)[5];
p_arr parr2 = &arr;
printf("%p\n", parr1); // 两地址相同
printf("%p\n", parr2);
return 0;
}
更改方式:
typedef int(*p_arr)[5];
例3:函数指针
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int main()
{
// 1.
int(*pfun1)(int, int) = Add;
// 2.
typedef int (*p_fun)(int, int);
p_fun pfun2 = Add;
printf("%p\n", pfun1); \\ 两者打印一样
printf("%p\n", pfun2);
return 0;
}
更改方式:
typedef int (*p_fun)(int, int);
由上代码 2 可以使用 typedef 进行缩减
void (*signal(int, void(*)(int)))(int);
typedef void(*p_arr)(int);
p_arr signal(int, p_arr);
typedef 和 #define
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
typedef int* int_p;
#define INT_P int*
int main()
{
int_p p1, p2; // p1 p2 为指针变量
INT_P p3, p4; // P3 为指针变量 ;p4 为整形变量
// 因为 int* p3, P4; p3 将*用掉后,p4没有了*
return 0;
}
函数指针数组
(谁在后方谁是名词)函数指针数组 = 数组
一种存放函数指针的数组
书写方式:
为元素类型,*后加 name[ ]
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
int Sum(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x * y;
}
int main()
{
//类型都为 int(int,int)
int (*arr[])(int, int) = {Add, Sum, Mul, Div};
return 0;
}
书写:
int (*arr[])(int, int) = {Add, Sum, Mul, Div};
更多推荐
所有评论(0)