【C语言基础】:深入理解指针(三)

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

深入理解指针

指针系列回顾
【C语言基础】:深入理解指针(一)
【C语言基础】:深入理解指针(二)

一、冒泡排序

冒泡排序的核心思想就是:两两相邻的元素进行比较。

#include<stdio.h>

void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = 0;
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
可以看到,这段代码对arr数组进行了排序,但这个代码还有一些缺陷,那就是无论数组内部的元素是否有序,他都会循环9次,这样肯定是不合理的,要进行优化一下。

我们在bubble_sort函数的第一层循环里面定义一个变量flag,进入第二层循环就修改flag的值,第二层循环结束时给变量flag来个判断,如果变量flag没有发生改变,说明没有进入第二层循环,也就是说这时数组里的元素是有序的,就会直接跳出第一层循环。另外,我们还可以在最外面定义一个全局变量用来计数,每进行一次元素交换就会自增1。

#include<stdio.h>
int count = 0;
bubble_sort(int arr[], int sz)  //参数接收数组元素个数
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;  //假设这⼀趟已经有序了
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			count++;
			if (arr[j] > arr[j + 1])
			{
				flag = 0;  //发⽣交换就说明,⽆序
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 1)  //这⼀趟没交换就说明已经有序,后续⽆序排序了
			break;
	}
}

int main()
{
	int arr[] = { 0,9,8,6,5,3,1,2,4,7 };
	int sz = sizeof(arr) / sizeof(arr[0]);  // 求出数组中的元素个数
	bubble_sort(arr, sz);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	printf("%d\n", count);
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
运行之后可以发现,代码的运行效率明显提升了,理论来说上述数组元素在未优化的代码下运行是要进行45次交换的,现在明显次数减少了。

二、二级指针

通过前面的知识我们知道,指针变量也是一个变量,只要是一个变量就会有地址,那么,指针变量的地址放在哪里呢?
我们把存放地址的指针称为二级指针,也就是指针的指针

#include<stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	int** ppa = &pa;
	return 0;
}

而三级指针就是存放二级指针变量的地址,四级指针、五级指针以此类推…

对于二级指针的运算有:

  • *ppa通过对ppa进行解引用,就可以找到pa,*ppa其实访问的就是pa
int b = 20;
*ppa = &b;  // 等价于pa = &b
  • **pa先通过*ppa找到pa,然后对pa进行解引用操作:*pa,找到的就是a。
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;

三、指针数组

首先我们要弄懂一个问题:指针数组到底是一个指针还是一个数组?
这里我们可以类比一下:

整数数组:就是一个存放整型的数组
字符数组:就是一个存放字符的数组

那指针数组呢?没错,就是存放指针的数组
【C语言基础】:深入理解指针(三),c语言,开发语言
指针数组里的每个元素都是用来存放地址(指针)的。

如下图:
【C语言基础】:深入理解指针(三),c语言,开发语言
通过这张图可以看到,指针数组里的每一个元素都是一个指针,而这里面的每一个指针又可以指向一块区域。

3.1 指针数组模拟二维数组
#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };
	//数组名是数组首元素的地址,类型是int*的,就可以存放在parr数组中
	int* parr[] = { arr1, arr2, arr3 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", parr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
【C语言基础】:深入理解指针(三),c语言,开发语言
parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数组中的元素。
注意:这只是利用指针数组模拟的二维数组,并非是真的二维数组,因为每一行的地址并非连续的

四、字符指针变量

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

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

还有一种使用方式如下:

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

【C语言基础】:深入理解指针(三),c语言,开发语言
注意:这里const char* pc = “hello world”; 特别容易让人认为是把字符串hello world放到字符指针pc里了,但其实本质上是字符串hello world 首字符的地址放到了pc中。
【C语言基础】:深入理解指针(三),c语言,开发语言
上面的代码的意思是把一个常量字符串的首字符h的地址存放到指针变量pc中。

下面是一道和字符串相关的题,我们可以学一下:

#include<stdio.h>
int main()
{
	char str1[] = "hello world";
	char str2[] = "hello world";
	const char* str3 = "hello world";
	const char* str4 = "hello world";
	if (str1 == str2)
		printf("str1 and str2 are same\n");  // 序号1
	else
		printf("str1 and str2 are not same\n");  // 序号2
	if (str3 == str4)
		printf("str3 and str4 are same\n");  // 序号3
	else
		printf("str3 and str4 are not same\n");  // 序号4
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
运行之后我们会发现,打印的是序号2和序号3的语句,这是为什么呢?
这里的str3和str4指向的是同一个常量字符串。C/C++会把常量字符串存储到一个单独的内存区域,当几个指针指向同一个字符串的时候,它们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

五、数组指针变量

5.1 数组指针变量是什么?

上面在学指针数组的时候我们知道,指针数组是数组元素为指针的数组。那么数组指针是什么呢?
上面学习指针数组的时候类比了一下,那么这里不妨也来类比一下:

  • 整型指针变量int * pint; 存放的是整型变量的地址,能够指向整形数据的指针。
  • 浮点型指针变量float * pf; 存放浮点型变量的地址,能够指向浮点型数据的指针。

那么数组指针就是存放数组的地址,能够指向数组数据的指针变量

我们判断一下下面那个是数组指针

int *p1[10];
int (*p2)[10];

int * p1[10]; 是一个指针数组,是 10 个整型指针的数组。
int ( * p2)[10]; 是数组指针,表示一个指向包含 10 个整型数据的数组的指针。因为 p2 是一个指针,所以 p2 是一个指针类型。

数组指针变量

int (*p2)[10];

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

5.2 数组指针变量的初始化

数组指针变量是用来存放数组地址的,那怎么获得数组的地址呢?其实就是我们之前学的 &数组名

int main()
{
	int arr[10] = { 0 };
	&arr;  //得到的就是数组的地址
	return 0;
}

如果要存放个数组的地址,就得存放在数组指针变量中,如下:

int main()
{
	int arr[10] = { 0 };
	int(*pa)[10] = &arr;
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
在调试的过程中我们也可以看到 &arrpa的类型是完全一致的。

数组指针类型解析:

int (*p) [10] = &arr;
 |    |    |
 |    |    |
 |    |    | p指向数组的元素个数
 |    p是数组指针变量名
 p指向的数组的元素类型

六、二维数组传参的本质

有了数组指针的理解,我们就能够讲⼀下二维数组传参的本质了。
过去我们有一个二维数组的需要传参给⼀个函数的时候,我们是这样写的:

#include<stdio.h>

void test(int a[3][5], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf("%d ", a[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} };
	test(arr, 3, 5);
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
这里实参是二维数组,形参也写成⼆维数组的形式,那还有什么其他的写法吗?
首先我们再次理解⼀下二维数组,二维数组其实可以看做是每个元素是⼀维数组的数组,也就是⼆维数组的每个元素是⼀个⼀维数组。那么⼆维数组的首元素就是第一行,是个⼀维数组。
如下图:
【C语言基础】:深入理解指针(三),c语言,开发语言
所以,根据数组名是数组首元素的地址这个规则,⼆维数组的数组名表示的就是第一行的地址,是⼀维数组的地址。根据上面的例子,第一行的⼀维数组的类型就是 int [5] ,所以第一行的地址的类型就是数组指针类型 int(*)[5] 。那就意味着⼆维数组传参本质上也是传递了地址,传递的是第一行这个⼀维数组的地址,那么形参也是可以写成指针形式的。如下:

#include<stdio.h>

void test(int(*p)[5], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf("%d ", *((*p + 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} };
	test(arr, 3, 5);
	return 0;
}

【C语言基础】:深入理解指针(三),c语言,开发语言
总结:二维数组传参,形参的部分可以写成数组,也可以写成指针形式。文章来源地址https://www.toymoban.com/news/detail-838292.html

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

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

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

相关文章

  • C语言指针基础

    目录 前言 本期介绍内容: 一、指针是什么? 二、指针和指针类型 指针类型的意义: 三、野指针 3.1什么是野指针? 3.2野指针的成因 1.指针未初始化 2.指针越界访问 3.指针指向的那块空间已经释放(还给操作系统了) 3.3如何规避野指针 四、指针运算 4.1指针加减整数 4.2指针

    2024年02月12日
    浏览(45)
  • C语言基础之——指针(上)

    前言:小伙伴们又见面啦!本期内容,博主将展开讲解有关C语言中指针的上半部分基础知识,一起学习起来叭!!! 目录 一.什么是指针 二.指针类型 1.指针的解引用 2.指针+-整数 三.野指针 1.野指针成因 (1)指针未初始化  (2)指针越界访问 2.如何规避野指针 四.总结 指针

    2024年02月11日
    浏览(49)
  • C语言基础之——指针(下)

    前言:本篇文章将继续讲解有关指针的剩余基础知识。 学无止境,一起加油叭!! 目录 一.指针运算 1.指针 +- 整数  2.指针的关系运算  3.指针 - 指针 二.指针与数组 三.二级指针 四.指针数组 总结 指针运算包括以下三种: 指针 +- 整数 指针 - 指针 指针的关系运算 我们尝试用

    2024年02月11日
    浏览(35)
  • 【C语言基础入门】二级指针、一维数组与指针、二维数组与指针

    在学习C语言的过程中,理解指针的概念是非常重要的。指针提供了一种直接访问内存地址的方式,使得我们可以更加灵活地管理数据和内存。在本文中,我们将介绍C语言中的二级指针、一维数组与指针,并通过通俗易懂的语言和示例代码来帮助读者理解这些概念。 二级指针

    2024年02月05日
    浏览(57)
  • C语言-基础语法学习-3 二级指针

    当涉及到多级指针时,C语言的灵活性和强大的指针功能可以得到充分的发挥。二级指针是指指向指针的指针,也被称为指向指针的引用。 使用二级指针可以实现以下功能: 动态内存分配:通过二级指针可以动态地分配内存块,并将其地址传递给其他函数或模块进行操作。这

    2024年02月12日
    浏览(45)
  • C语言 指针声明和定义 - C语言零基础入门教程

    目录 [一.指针简介] [1.内存] [2.内存地址] [3.指针声明] [二.指针类型] [三.声明并初始化一个指针] [1.声明指针并直接初始化 – 推荐] [2.先声明指针在初始化 – 不推荐] [四.查看指针地址和指针的值] [五.NULL 指针 – 空指针] [六.重点总结] [七.猜你喜欢] 零基础 C/C++ 学习路线推荐

    2024年03月22日
    浏览(43)
  • 【05】STM32·HAL库开发-C语言基础知识 | stdint.h介绍 | 位操作 | 宏定义的使用 | 条件编译 | extern声明 | typdef使用 | 结构体、指针、代码规范介绍。

      stdint.h 是从 C99 中引进的一个标准 C 库的文件,可以在MDK5的安装路径:D:MDK5.34ARMARMCCinclude中找到。   stdint.h 定义了很多类型别名,将有符号的char类型定义别名为int8_t等,使用此套别名有易于移植。   在MDK中需要配置才能支持使用S99标准, 默认是勾选的 。   只

    2024年02月08日
    浏览(44)
  • 逍遥自在学C语言 | 指针的基础用法

    在C语言中,指针是一项重要的概念,它允许我们直接访问和操作内存地址。 可以说,指针是C语言一大优势。用得好,你写程序如同赵子龙百万军中取上将首级;用得不好,则各种问题层出不穷,有种双拳难敌四手的感觉。 本文将介绍指针的基础知识,包括指针的定义、初始

    2024年02月09日
    浏览(44)
  • 【C语言初阶】带你轻松掌握指针基础知识完结篇——野指针,指针运算,指针和数组,二级指针

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,这里是君兮_,今天继续给大家更新0基础入门C语言的内容,我们这次主要更新的依然是初阶指针的基础知识 废话不多说咱们直接开始吧!! 概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有

    2024年02月16日
    浏览(47)
  • 【C语言】指针超级无敌金刚霹雳进阶(但不难,还是基础)

    点击这里访问我的博客主页~~ 对指针概念还不太清楚的点击这里访问上一篇指针初阶2.0 上上篇指针初阶1.0 谢谢各位大佬的支持咯 今天我们一起来学习指针进阶内容 指针变量有 字符指针变量 , 数组指针变量 和 函数指针变量 char* 叫做字符指针 一般这么来使用: 通过指针存

    2024年03月09日
    浏览(44)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包