字符指针

#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};

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐