【进阶C语言】指针的进阶(万字图文详解)

这篇具有很好参考价值的文章主要介绍了【进阶C语言】指针的进阶(万字图文详解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:

  1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
  2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
  3. 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
  4. 指针的运算。

这个章节,我们继续探讨指针的高级主题。

1. 字符指针

在指针的类型中我们知道有一种指针类型为字符指针 char* ;
一般使用:

#include <stdio.h>
int main()
{
	char ch = 'w';
	char* pc = &ch;
	*pc = 'w';
	return 0;
}

还有一种使用方式如下:

#include <stdio.h>
int main()
{
	const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
	printf("%s\n", pstr);
	return 0;
}

代码 const char* pstr = “hello bit.”;

特别容易让同学以为是把字符串 hello bit 放到字符指针 pstr 里了,但是本质是把字符串 hello bit. 首字符的地址放到了pstr中。

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
上面代码的意思是把一个常量字符串的首字符 h 的地址存放到指针变量 pstr 中。
那就有可这样的面试题:

#include <stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";

	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";

	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

这里最终输出的是:
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针。指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4不同。

2. 指针数组

在《指针》章节 我们也学了指针数组,指针数组是一个存放指针的数组。
这里我们再复习一下,下面指针数组是什么意思?
类比一下:

  1. 字符数组 - 存放字符的数组
    int arr1 [ 10 ] ;
  2. 整型数组 - 存放整型的数组
    int arr2 [ 5 ] ;
  3. 指针数组 - 存放的就是指针
    存放字符指针的数组 - 字符指针数组
    char* arr3 [ 5 ] ;
    存放整型指针的数组 - 整型指针数组
    int* arr4 [ 6 ] ;
    举一个生动的例子:
int main()
{
	char* arr[] = { "abcdef", "hehe", "qwer" };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		printf("%s\n", arr[i]);
	}
	return 0;
}

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

再举一个例子:

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	//arr[i] == *(arr+i)
	//arr是一个存放整型指针的数组
	int* arr[] = { arr1, arr2, arr3 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			//printf("%d ", arr[i][j]);
			printf("%d ", *(arr[i]+j));
		}
		printf("\n");
	}
	return 0;
}

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

3. 数组指针

3.1 数组指针的定义

数组指针是指针?还是数组?
答案是:指针。
我们已经熟悉:
整形指针: int * pint; 能够指向整形数据的指针。
浮点型指针: float * pf; 能够指向浮点型数据的指针。
那数组指针应该是:能够指向数组的指针。
类比:

  1. 整型指针 - 指向整型的指针
    int a = 10 ;
    int* p = &a ;
  2. 字符指针 - 指向字符的指针
    char ch = ’ w ’ ;
    char* pc = &ch ;
  3. 数组指针 - 指向数组的指针
    int arr [ 10 ] ;
    int (*pa ) [ 10 ] = &arr ; //取出的是数组的地址
    char arr[ 10 ] ;
    char (*pc) [ 10 ] &arr ;
    int * arr [ 5 ] ;
    int * (*p ) [ 5 ] = &arr ;
    下面代码哪个是数组指针?
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?

解释:

int (p)[10];
//解释:p先和
结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
//这里要注意:[ ]的优先级要高于号的,所以必须加上( )来保证p先和结合。

总结:

指针数组 - 是数组 - 是一种存放指针的数组。
数组指针 - 是指针 - 是一种指向数组的指针 - 存放的是数组的地址。

//指针数组 - 是数组 - 是一种存放指针的数组
//数组指针 - 是指针 - 是一种指向数组的指针 - 存放的是数组的地址

int main()
{
	//指针数组
	char* arr[4];
	//数组指针
	int arr[5];
	int (*p)[5] = &arr;

	return 0;
}

3.2 &数组名VS数组名

对于下面的数组:

int arr[10];

arr 和 &arr 分别是啥?
我们知道arr是数组名,数组名表示数组首元素的地址。
那&arr数组名到底是啥?
我们看一段代码:

int main()
{
	int arr[10] = { 0 };
	
	printf("%p\n", arr);

	printf("%p\n", &arr[0]);
	
	printf("%p\n", &arr);

	return 0;
}

运行结果如下:
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
可见数组名和&数组名打印的地址是一样的。
难道两个是一样的吗?
我们再看一段代码:

//数组名绝大部分情况下是数组首元素的地址
//但是有2个例外:
//1. sizeof(数组名) - sizeof内部单独放一个数组名的时候,数组名表示的整个数组,计算得到的是数组的总大小
//2. &arr  - 这里的数组名表示整个数组,取出的是整个数组的地址,从地址值的角度来讲和数组首元素的地址是一样的,但是意义不一样
//

int main()
{
	int arr[10] = { 0 };
	//printf("%d\n", sizeof(arr));
	printf("%p\n", arr);//int * 
	printf("%p\n", arr+1);//4

	printf("%p\n", &arr[0]);//int* 
	printf("%p\n", &arr[0]+1);//4

	printf("%p\n", &arr);//int(*)[10]
	printf("%p\n", &arr+1);//40
	int (*p)[10] = &arr;//p是一个数组指针
	//int(*)[10]
	return 0;
}

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
根据上面的代码我们发现,其实&arr和arr,虽然值是一样的,但是意义应该不一样的。
实际上: &arr 表示的是数组的地址,而不是数组首元素的地址。(细细体会一下)
本例中 &arr 的类型是: int(*)[10] ,是一种数组指针类型
数组的地址+1,跳过整个数组的大小,所以 &arr+1 相对于 &arr 的差值是40。
注意:

数组名绝大部分情况下是数组首元素的地址
但是有2个例外:

  1. sizeof(数组名) - sizeof内部单独放一个数组名的时候,数组名表示的整个数组,计算得到的是数组的总大小
  2. &arr - 这里的数组名表示整个数组,取出的是整个数组的地址,从地址值的角度
    讲和数组首元素的地址是一样的,但是意义不一样

3.3 数组指针的使用

那数组指针是怎么使用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地址。
看代码:

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	int sz = sizeof(arr) / sizeof(arr[0]);
	int (* p)[10] = &arr;
	int i = 0;
	//p  --- &arr
	//*p --- *&arr
	//*p --- arr
	//虽然对,但是不推荐
	for (i = 0; i < sz; i++)
	{
		printf("%d ", (*p)[i]);
	}
	//虽然对,但是不推荐
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *((*p) + i));
	}

	//使用指针来访问
	int* p = arr;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
	}

	//下标的形式访问数组
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

一个数组指针的使用:

#include <stdio.h>
void print(int arr[3][5], int r, int c)
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
	//二维数组的数组名,也表示首元素的地址
	//二维数组的首元素是第一行
	//首元素的地址就是第一行的地址,是一个一维数组的地址
	//
	print(arr, 3, 5);
	return 0;
}

用数组指针来做:

#include <stdio.h>
void print(int(*arr)[5], int r, int c)
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			//printf("%d ", *(*(arr + i) + j));//arr[i]
			printf("%d ", arr[i][j]);//arr[i]
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
	//二维数组的数组名,也表示首元素的地址
	//二维数组的首元素是第一行
	//首元素的地址就是第一行的地址,是一个一维数组的地址
	//
	print(arr, 3, 5);
	return 0;
}

图片讲解:
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
学了指针数组和数组指针我们来一起回顾并看看下面代码的意思:

1. int arr[5];
2. int *parr1[10];
3. int (*parr2)[10];
4. int (*parr3[10])[5];

第一个是数组
第二个是指针数组
第三个是数组指针
第四个原理:parr3是数组,数组中存放的指针,该指针指向的又是数组,所以是指针数组里面存放的数组指针

第四个图片讲解:
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

4. 数组参数、指针参数

在写代码的时候难免要把【数组】或者【指针】传给函数,那函数的参数该如何设计呢?

4.1 一维数组传参

#include <stdio.h>
void test(int arr[])//ok?
{}
void test(int arr[10])//ok?
{}
void test(int* arr)//ok?
{}
void test2(int* arr[20])//ok?
{}
void test2(int** arr)//ok?
{}
int main()
{
	int arr[10] = { 0 };
	int* arr2[20] = { 0 };
	test(arr);
	test2(arr2);
}
}

结果是都可以运行。

结论:
一维数组传参,传参可以是数组,也可以是指针的,当形参是指针的时候,要注意类型。

4.2 二维数组传参

void test(int arr[3][5])//ok?可以
{}
void test(int arr[][])//ok?不可以
{}
void test(int arr[][5])//ok?可以
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int* arr)//ok?不可以
{}
void test(int* arr[5])//ok?不可以
{}
void test(int(*arr)[5])//ok?可以
{}
void test(int** arr)//ok?不可以
{}
int main()
{
	int arr[3][5] = { 0 };
	test(arr);
}

结论:
二维数组传参
传参可以是指针,也可以是数组
如果是数组,行可以省略,但是列不能省略
如果是指针,传过去的是第一行的地址,形参就应该是数组指针

4.3 一级指针传参

#include <stdio.h>
void print(int* p, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d\n", *(p + i));
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//一级指针p,传给函数
	print(p, sz);
	return 0;
}

思考:

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

4.4 二级指针传参

#include <stdio.h>
void test(int** ptr)
{
	printf("num = %d\n", **ptr);
}
int main()
{
	int n = 10;
	int* p = &n;
	int** pp = &p;
	test(pp);
	test(&p);
	return 0;
}

思考:

当函数的参数为二级指针的时候,可以接收什么参数?

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

5. 函数指针

类比方法:
整型指针 - 指向整型的指针 int*
字符指针 - 指向字符的指针 char*
数组指针 - 指向数组的指针 int arr[ 10 ]* ; int( p )[ 10 ] = & arr ;
函数指针 - 指向函数的指针 int

数组指针中存放的是数组的地址
函数指针中存放的应该是函数的地址
函数有地址吗?
首先看一段代码:

#include <stdio.h>
void test()
{
	printf("hehe\n");
}
int main()
{
	printf("%p\n", test);
	printf("%p\n", &test);
	return 0;
}

输出的结果:
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
输出的是两个地址,这两个地址是 test 函数的地址。
数组:
数组名
&数组名

函数名和&函数名 都是函数的地址,没有区别。
那我们的函数的地址要想保存起来,怎么保存?
下面我们看代码:

void test()
{
	printf("hehe\n");
}
//下面pfun1和pfun2哪个有能力存放test函数的地址?
void (*pfun1)();
void* pfun2();

首先,能给存储地址,就要求pfun1或者pfun2是指针,那哪个是指针?
答案是:

pfun1可以存放。pfun1先和*结合,说明pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回值类型为void。

举一个例子:

int Add(int x, int y)
{
	return x + y;
}

//&函数名得到就是函数的地址

int main()
{
	//printf("%p\n", &Add);
	//printf("%p\n", Add);
	//pf就是函数指针
	int (* pf)(int, int) = Add;//函数的地址要存起来,就得放在【函数指针变量】中
	
	int ret = (*pf)(3, 5);
	//int ret = Add(3, 5);
	//int ret = pf(3, 5);

	printf("%d\n", ret);

	return 0;
}

在练习一个函数指针的例子

char* test(int c, float* pf)
{

}
int main()
{
	char* (*pt)(int, float*) = test;

	return 0;
}

阅读两段有趣的代码:

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);
//代码1
int main()
{
	//1. 将0强制类型转换为void (*)() 类型的函数指针
	//2. 这就意味着0地址处放着一个函数,函数没参数,返回类型是void
	//3. 调用0地址处的这个函数
	//下面代码是一次函数调用
    (*( void (*)() ) 0)();
	return 0;
}
  1. 将0强制类型转换为void (*)() 类型的函数指针
  2. 这就意味着0地址处放着一个函数,函数没参数,返回类型是void
  3. 调用0地址处的这个函数
typedef void(*pf_t)(int);//将void(*)(int)类型重新起个别名叫pf_t

//
typedef void(*pf_t2)(int);//pf_t2是类型名
void(*pf)(int);//pf是函数指针变量的名字
	//代码2
int main()
{
	void (* signal(int, void(*)(int) ) )(int);
	//
	pf_t signal(int, pf_t);
	//上述的代码是一个函数的声明
	//函数的名字是signal
	//signal函数的参数第一个是int类型,第二个是void(*)(int)类型的函数指针
	//该函数指针指向的函数参数是int,返回类型是void
	// 
	//signal函数的返回类型也是一个函数指针
	//该函数指针指向的函数参数是int,返回类型是void
	//
	//void (* signal(int, void(*)(int)))(int)
	return 0;
}

上述的代码是一个函数的声明
函数的名字是signal
signal函数的参数第一个是int类型,第二个是void(*)(int)类型的函数指针
该函数指针指向的函数参数是int,返回类型是void
signal函数的返回类型也是一个函数指针
该函数指针指向的函数参数是int,返回类型是void

6. 函数指针数组

数组是一个存放相同类型数据的存储空间,那我们已经学习了指针数组,
比如:

int *arr[10];
//数组的每个元素是int*

那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组,那函数指针的数组如何定义呢?

int (*parr1[10])();
int *parr2[10]();
int (*)() parr3[10];

答案是:parr1
parr1 先和 [] 结合,说明 parr1是数组,数组的内容是什么呢?
是 int (*)() 类型的函数指针。

int Add(int x, int y)
{
	return x + y;
}
int Sub(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 (* pf[4])(int, int) = {Add, Sub, Mul, Div};
	//0 1 2 3
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int ret = pf[i](8, 4);
		printf("%d\n", ret);
	}

	return 0;
}

函数指针数组的用途:转移表
例子:(计算器)
先写一个冗余的计算器

int Add(int x, int y)
{
	return x + y;
}
int Sub(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;
}

//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
	printf("******************************\n");
	printf("****   1. add    2.sub   *****\n");
	printf("****   3. mul    4.div   *****\n");
	printf("****   0. exit           *****\n");
	printf("******************************\n");
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

使用函数指针数组的实现:

int Add(int x, int y)
{
	return x + y;
}
int Sub(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;
}
//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
	printf("******************************\n");
	printf("****   1. add    2.sub   *****\n");
	printf("****   3. mul    4.div   *****\n");
	printf("****   0. exit           *****\n");
	printf("******************************\n");
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;

	//转移表 - 函数指针的数组
	int (*pfArr[])(int, int) = { NULL, Add, Sub, Mul, Div };
	//0    1    2    3    4

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		if (input == 0)
		{
			printf("退出计算器\n");
			break;
		}
		else if (input >= 1 && input <= 4)
		{
			printf("请输入两个操作数:>");
			scanf("%d %d", &x, &y);
			ret = pfArr[input](x, y);
			printf("%d\n", ret);
		}
		else
		{
			printf("选择错误\n");
		}
	} while (input);
	return 0;
}

7. 指向函数指针数组的指针

指向函数指针数组的指针是一个 指针
指针指向一个 数组 ,数组的元素都是 函数指针 ;
如何定义?

void test(const char* str)
{
	printf("%s\n", str);
}
int main()
{
	//函数指针pfun
	void (*pfun)(const char*) = test;
	//函数指针的数组pfunArr
	void (*pfunArr[5])(const char* str);
	pfunArr[0] = test;
	//指向函数指针数组pfunArr的指针ppfunArr
	void (*(*ppfunArr)[5])(const char*) = &pfunArr;
	return 0;
}

再举了一个例子:

int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}

int main()
{
	int (*pf)(int, int) = Add;
	//函数指针数组
	int (* pfArr[4])(int, int) = {Add, Sub};
	//
	int (*(* ppfArr)[4])(int, int) = &pfArr;//ppfArr是一个指向函数指针数组的指针变量

	return 0;
}

8. 回调函数

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

拿一下刚刚的计算器代码来优化讲解一下回调函数:

#include <stdio.h>



int Add(int x, int y)//回调函数
{
	return x + y;
}
int Sub(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;
}
//写一个计算器能完成整数的+-*/
//增加: << >> & | ^ && ||
//
void menu()
{
	printf("******************************\n");
	printf("****   1. add    2.sub   *****\n");
	printf("****   3. mul    4.div   *****\n");
	printf("****   0. exit           *****\n");
	printf("******************************\n");
}

void Calc(int(*pf)(int, int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:>");
	scanf("%d %d", &x, &y);
	ret = pf(x, y);
	printf("%d\n", ret);
}

int main()
{
	int input = 0;
	
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			Calc(Add);
			break;
		case 2:
			Calc(Sub);
			break;
		case 3:
			Calc(Mul);
			break;
		case 4:
			Calc(Div);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

此时代码上面标注的就是回调函数。

图片展示过程:

c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法
c语言指针从底层原理到花式技巧,进阶C语言,c语言,c++,开发语言,经验分享,算法

如果这份博客对大家有帮助,希望各位给恒川一个免费的点赞作为鼓励,并评论收藏一下,谢谢大家!!!
制作不易,如果大家有什么疑问或给恒川的意见,欢迎评论区留言。
下一期要用到sqort库函数来讲解回调函数,希望大家期待一下!文章来源地址https://www.toymoban.com/news/detail-788856.html

到了这里,关于【进阶C语言】指针的进阶(万字图文详解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言:指针详解【进阶】后篇

    前言: 在C语言:指针详解【进阶】前篇中我们深入学习了 字符指针 , 数组指针 , 指针数组 以及 数组传参和指针传参 。我们对指针的应用有了较为深刻的认识,今天这里我们将更加深入的进行对更复杂的指针的探究。 在前面我们知道一个指针变量可以指向一块内存的地

    2024年02月05日
    浏览(25)
  • 【C语言进阶】⑥函数指针详解

    1.概念 函数指针 :首先它是一个指针,一个指向函数的指针,在内存空间中存放的是函数的地址; 请看示例: 解析:parr是一个指向数组的指针,存放的是数组的地址; 所以: 数组指针 —存放数组地址的指针; 数组名 —得到的就是数组的地址; 那么我们可以不可以这么认

    2024年02月02日
    浏览(27)
  • 【C语言】进阶指针,超详解,含丰富代码示例

    这里是初阶的链接,方便大家对照查看!!!添加链接描述 大家好呀,今天和大家将指针进阶的知识进行分享,这块是指针的难点部分,希望博主对其的理解可以帮助到大家!!! 字符指针 数组指针 指针数组 函数指针 函数指针数组 指向函数指针数组的指针 在指针的类型

    2024年02月13日
    浏览(26)
  • 【数据结构】深入浅出理解快速排序背后的原理 以及 版本优化【万字详解】(C语言实现)

    快速排序是 Hoare 于1962年提出的一种 二叉树结构 的 交换排序 方法。 任取待排序元素序列中的 某元素作为基准值 ,按照该排序码将待排序集合 分割成两子序列 , 左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值 ,然后最左右子序列重复该过程,直到所

    2024年02月05日
    浏览(86)
  • C生万物 | 指针入门到进阶就看这篇了【十万字吐血整理,收藏学习】

    文章篇幅较长,可前往电脑端进行学习💻 之前很多粉丝私信我说 C语言指针 怎么这么难,看了很多视频都学不懂,于是我写了一篇有关指针从入门到进阶的教学,帮助那些对指针很困扰的同学有一个好的学习途径,下面是本文的参考配套视频,出自b站【鹏哥C语言】,鹏哥讲

    2024年02月03日
    浏览(39)
  • 【C++】智能指针(万字详解)

    (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是 Scort 目前状态:大三非科班啃C++中 🌍博客主页:张小姐的猫~江湖背景 快上车🚘,握好方向盘跟我有一起打天下嘞! 送给自己的一句鸡汤🤔: 🔥真正的大师永远怀着一颗学徒的心 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏 🎉🎉

    2024年02月02日
    浏览(29)
  • Redis进阶底层原理-Cluster集群底层

    Redis底层原理篇

    2024年02月16日
    浏览(26)
  • 【C语言】指针数组测试题(1万字长文)

    江南可采莲,莲叶何田田。鱼戏莲叶间。鱼戏莲叶东,鱼戏莲叶西,鱼戏莲叶南,鱼戏莲叶北。 — 两汉·汉乐府《江南》 这篇博客我们将会讲解一些习题,习题是有关于数组和指针的,数组方面的习题也能帮助我们更好的理解sizeof和strlen,指针的习题也全方位锻炼我们对指

    2024年02月16日
    浏览(34)
  • JAVASE进阶:强推!源码分析——字符串拼接底层原理、StringBuilder底层原理

    👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:JAVASE进阶:String常量池内存原理分析、字符串输入源码分析 📚订阅专栏:JAVASE进阶 希望文章对你们有所帮助 这是比较重要的内容,学习原理很重要,啃源码也很重要!!! 字符串 常量 的

    2024年02月20日
    浏览(33)
  • Java SE 继承和多态 (图文搭配,万字详解!!)

    目录 1.继承 1.1 为什么需要继承 1.2 继承概念  1.3 继承的语法 1.4 父类成员访问 1.4.1 子类中访问父类的成员变量 1.4.2 子类中访问父类的成员方法  1.5 super  1.6 子类构造方法 1.7 super和this 1.8 再谈初始化 1.9 protected 1.10 继承方式  1.11 final 1.12 继承与组合 2

    2024年02月05日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包