C语言指针精简版(二)

news2025/1/17 21:52:41

目录

数组名的理解

使⽤指针访问数组

⼀维数组传参的本质

冒泡排序

⼆级指针及其解引用

指针数组

实例:指针数组模拟⼆维数组

数组名的理解

对于数组名表示的意义一共有三种情况:

*1、数组名:表示数组⾸元素地址。

*2、sizeof(数组名):表⽰整个数组,计算整个数组的⼤⼩,单位是字节

*3、&数组名,表⽰整个数组,取出的是整个数组的地址

小拓展:

        在实际应用中,*1为一般情况,*2、*3为特殊情况,编译器在遇到arr[i]的时候会将它转为*(arr+i)的形式进行计算,所以理论上有这种写法,但不推荐:

arr[i]   ==   *(arr+i)    ==  *(i+arr)  ==  i[arr]

同时这也是为什么我们有了数组首元素地址arr和一个[i]就可以通过for循环实现遍历数组元素

#include <assert.h>
#include <stdio.h>
int my_strlen(const char* str)    //统计所求字符串长度函数,加上const修饰*str,表示不能修改这个字符串,防止修改str的内容
{
    int count = 0;
    assert(str != NULL);    //确保了指针的有效性,str为空指针就报错了。
    while (*str != '\0')
    {
        count++;     //次数加一
        str++;       //地址加一
    }
    return count;   //返回统计的个数
}

int main()
{
    char arr[] = "hello bit";
    int len = my_strlen(arr);
    printf("%d\n", len);
    return 0;
}

使⽤指针访问数组

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	//输⼊
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//输⼊
	int* p = arr;
	for (i = 0; i < sz; i++)
	{
		scanf_s("%d", p + i);
		//scanf("%d", arr+i);//也可以这样写
        //&arr[i]也行
	}
	//输出
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(p + i));
        //写成printf("%d ", p[i]);也许
	}
	return 0;
}

⼀维数组传参的本质

        我们之前都是在函数外部计算数组的元素个数,那我们可以把函数传给⼀个函数后,函数内部求数组的元素个数吗?
#include <stdio.h>
void test(int arr[])
{
	int sz2 = sizeof(arr) / sizeof(arr[0]);
	printf("sz2 = %d\n", sz2);
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz1 = sizeof(arr) / sizeof(arr[0]);
	printf("sz1 = %d\n", sz1);
	test(arr);
	return 0;
}

        很明显不可以,这是因为我们传递的是数组名,而它又代表数组⾸元素的地址,那么在函数内部我们写sizeof(arr) 计算的其实是⼀个指针变量的⼤⼩⽽不是数组的⼤⼩......

#include <stdio.h>
void test1(int arr[])//参数写成数组形式,本质上还是指针
{
	printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
}
}
void test2(int* arr)//参数写成指针形式
{
	printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	test1(arr);
	test2(arr);
	return 0;
}

所以应将计算数组元素个数的操作放在传参前进行

总结:⼀维数组传参,传递的是数组首元素地址,形参的部分可以写成数组或指针的形式

冒泡排序

核心思想:两两相邻的元素进⾏⽐较
#include <stdio.h>
#include <stdbool.h>
void bubble_sort(int arr[], int sz)
{
	int i = 0;
	for (i = 0; i < sz - 1; i++)
	{
		_Bool flag = false;//flag用于标志是否进行了排序,假设整个序列不需要排序,将flag设为false
		int j = 0;
		for (j = 0; j < sz - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = true;//当进入if语句后,证明确实需要排序,此时将flag赋值为true
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		//如果整个数组仍需排循环序,那么在进行完一次内部foe循环后flag的值变为了true(因为进入了if语句)
		//如果整个数组已经排序完成不需要循环了,那么就不会进入if语句中修改flag的值,此时flag为false
		if (flag == false)//当外层for的一次循环执行至此时,如果flag的值仍为flase,则外层for循环break,若为true,则继续下一轮循环
			break;  
	}
}
int main()
{
	int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	//遍历打印冒泡排序后的数组元素
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

⼆级指针及其解引用

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪⾥?

答案:二级指针

指针变量前面有几个*就是几级指针,一般来说三级指针就是极限

#include <stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int* pa= &a;   
	printf("刚开始一级指针pa中存放的地址为:%p\n", pa);  
	*pa = 20;
	printf("对一级指针解引用一次后赋值20后变量a的值由10变为了:%d\n", a);
	int** ppa = &pa;
	**ppa = 100;
	printf("对二级指针解引用两次并赋值100后变量a的值由20变为了:%d\n", a);
	*ppa = &b;
	printf("对二级指针解引用一次并让其指向变量的b的地址后,一级指针pa中存放的地址为:%p\n", pa);
	return 0;
}

关于上述代码的解释:pa为一级指针它中存放的是变量a的地址,ppa为二级指针它中存放的是一级指针pa的地址,对二级指针ppa进行解引用操作,一次解引用后,可修改到指针变量pa在内存中存放的内容,两次解引用后,便可以修改到变量a在内存中存放的内容。

指针数组

学习指针数组之前,我们已经学过了多种数组比如:

  • 整型数组:存放整型的数组  int arr[10]
  • 字符数组:存放字符的数组  char arr[10]

        无论是整型数组还是字符数组,它们当中存放的元素类型都是一样的,而接下来要学的指针数组的也与它们相似......

指针数组的特点:数组指针的每个元素都是⽤来存放地址(指针)的(元素的类型都为指针类型)

指针数组的格式:指针变量类型 数组名[存放的地址(指针)个数]

实例:指针数组模拟⼆维数组

#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[3] = { arr1, arr2, arr3 };//将三个整型数组存放在int*类型的指针数组parr中,其中的arr1、arr2和arr3分别代表上述三个整型数组的首元素地址
    int i = 0;
    int j = 0;
    for (i = 0; i < 3; i++)    //i表示存放在int*类型的指针数组parr中的指针的个数
    {
        for (j = 0; j < 5; j++)    //j表示每一个指针指向的数组中的元素个数
        {
            printf("%d ", parr[i][j]);  // parr[i][j]  == >  *(*(parr+i)+j)
        }
        printf("\n");
    }
    return 0;
}

~over~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1114736.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中文编程工具开发语言开发的实际案例:触摸屏点餐软件应用场景实例

中文编程工具开发语言开发的实际案例&#xff1a;触摸屏点餐软件应用场景实例 软件特色&#xff1a; 1、功能实用&#xff0c;操作简单&#xff0c;不会电脑也会操作&#xff0c;软件免安装&#xff0c;已内置数据库。软件在关闭的时候&#xff0c;可以设置会员数据备份到U盘&…

@Controller与@RestController

总结 Controller &#xff1a;定义一个控制器类. RequestMapping &#xff1a;给出外界访问方法的路径&#xff0c;或者说触发路径 &#xff0c;触发条件。 具体解析访问路径到某个方法上. ResponseBody &#xff1a;标记Controller类中的方法。把return的结果变成JSON对象…

束从轩的“网红人设”,正在加重老乡鸡的割裂

文 | 螳螂观察 作者 | 图霖 “老乡鸡20周年&#xff0c;我请大家免费吃饭。” 和以往的每场活动一样&#xff0c;“网红老板”束从轩穿着印有老乡鸡品牌Logo的大红短袖T恤&#xff0c;向广大网友发出热情邀请&#xff0c;真诚得像是自家村口小卖部好客的大叔。 这并不是束从…

虹科 | 测试方案 | 汽车示波器 通讯网络(LIN/CAN/FlexRay)测试方案

通讯网络&#xff08;LIN/CAN/FlexRay&#xff09;测试 虹科CAN总线示波器把你的PC电脑变成一台功能强大的汽车测试工具&#xff0c;用于检测车辆网络各类通讯信号&#xff0c;如CAN Bus、CAN FD、LIN、FlexRay&#xff0c;还可以检测车上所有传感器和执行器的信号 串行译码 …

【动态规划】647. 回文子串、516. 最长回文子序列

提示&#xff1a;努力生活&#xff0c;开心、快乐的一天 文章目录 647. 回文子串&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;题目总结 516. 最长回文子序列&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3…

计算机网络学习笔记(四):网络层(待更新)

目录 4.1 IP地址、子网划分、合并超网 4.1.1 IP地址、子网掩码、网关 4.1.2 IP地址的编址方法1&#xff1a;IP地址分类&#xff08;A~E类地址、保留的IP地址&#xff09; 4.1.4 IP地址的编址方法2&#xff1a;子网划分&#xff08;等长、变长&#xff09; 4.1.5 IP地址的编…

uview组件使用笔记

图标样式 修改图标的样式 通过color参数修改图标的颜色通过size参数修改图标的大小&#xff0c;单位为rpx 效果图 <u-icon name"photo" color"#2979ff" size"28"></u-icon>图片图标 1.3.0 这里说的图片图标&#xff0c;指的是小…

RSTP详解:对比STP,到底改进了什么?

一、RSTP概述 IEEE 802.1W中定义的RSTP可以视为STP的改进版本&#xff0c;RSTP在许多方面对STP进行了优化&#xff0c;它的收敛速度更快&#xff0c;而且能够兼容STP。 二、RSTP对STP的改进 改进点1&#xff1a;端口角色 、 改进点2&#xff1a;端口状态 RSTP的状态规范缩…

5秒盾,加速乐

5秒盾 1.先清除网站cooke在刷新&#xff0c;如果出现的稍等就有可能是5秒盾 2.用fd抓搜索参数关键字定位到包 3.抓到包后查找加密参数 4.搜索看那个位置在赋值 5.搜索赋值的参数.去找加密的js 6.删除没用的代码&#xff0c;把检测指纹的赋值过去 7.还原代码在网站的页面…

搞懂TypeScript的类型声明

.d.ts 类型声明/定义文件是 TypeScript 重要的一部分&#xff0c; 希望本文可以带你搞懂下面几个问题&#xff1a; 类型声明是怎么被TypeScirpt识别到的?怎么使用第三方包的类型声明文件&#xff1f;TypeScript代码怎么编译生成类型声明文件&#xff1f;怎么为第三方包编写类…

94. 递归实现排列型枚举

题目&#xff1a; 94. 递归实现排列型枚举 - AcWing题库 思路&#xff1a; 1.全排列问题&#xff08;坑位问题&#xff09;---->递归搜索树---->用dfs深度优先搜索。 2. u表示当前坑位&#xff0c;state[u]表示坑位u存储的数据。因为不同坑位的数据不可以重复&#…

掌握高效创作的艺术:AI助你轻松生成高质量文章

在这个信息爆炸的时代&#xff0c;高效创作已成为一种必需。无论是写作、编辑&#xff0c;还是策划&#xff0c;我们都需要快速、准确地完成工作。然而&#xff0c;我们都有过这样的经历&#xff1a;在创作过程中&#xff0c;我们可能会遇到思路阻塞、词汇匮乏等问题&#xff0…

【IBIS 模型与仿真 - IBISWriter and Write_IBIS】

本文将介绍如何从用户设计中编写自定义IBIS模型。 本文是 SelectIO 解决方案中心&#xff08;Xilinx 答复 50924&#xff09;的设计助手部分&#xff08;Xilinx 答复 50926&#xff09;的一部分。 原文链接&#xff1a;https://support.xilinx.com/s/article/50957?languagee…

大势山维 | 全盘自主可控的实景三维中国建设解决方案

实景三维中国建设是面向新时期测绘地理信息事业服务于社会经济建设和生态文明建设的新定位、新需求。多年来&#xff0c;大势智慧与山维科技深耕数字化建设&#xff0c;以技术研发为立身之本&#xff0c;逐步成长为空间地理信息建设领域的领跑企业。 大势智慧围绕三维重建国产…

系统设计 - 我们如何通俗的理解那些技术的运行原理 - 第一部分:通信协议(1)

本心、输入输出、结果 文章目录 系统设计 - 我们如何通俗的理解那些技术的运行原理 - 第一部分&#xff1a;通信协议&#xff08;1&#xff09;前言通信协议REST API vs. GraphQL 对比GraphQL gRPC 运行原理步骤说明 什么是 WebHook &#xff08;网络钩子&#xff09;如何提升 …

[HCTF 2018] Hide and seek(buuctf),Unzip(ctfshow)

考核完对python软连接还是不熟悉&#xff0c;把这两道题在做一下 [HCTF 2018]Hideandseek 登录注册之后发现可以上传文件&#xff0c;随便上传一个 回显说不是zip文件 上传一个zip文件&#xff0c;发现他会自动解析 上传了一个 GIF89a <?php eval($_POST[zxc]); ?> …

mstsc改端口为33389

windows 远程默认端口3389不太安全&#xff0c;改成33389防下小人 把下面的2个文本存在后缀.reg的文件&#xff0c;双击导入注册表&#xff0c;"PortNumber"dword:0000826d 这个就是33389对应的端口号的16进制值&#xff0c;要想自己改成其它的换下值即可 Windows …

什么是超融合?超融合基础架构的本质是什么?

近年来各个行业对超融合&#xff08;Hyperconverged Infrastructure, 简称 HCI&#xff09;的关注度越来越高&#xff0c;但各家厂商的超融合架构实现方法各有不同。我们在这里不评判对错&#xff0c;也不去探究这些是不是真正的超融合&#xff0c;而是重新追本溯源&#xff0c…

jenkins 原理篇——pipeline流水线 声明式语法详解

大家好&#xff0c;我是蓝胖子&#xff0c;相信大家平时项目中或多或少都有用到jenkins&#xff0c;它的piepeline模式能够对项目的发布流程进行编排&#xff0c;优化部署效率&#xff0c;减少错误的发生&#xff0c;如何去写一个pipeline脚本呢&#xff0c;今天我们就来简单看…

行业追踪,2023-10-20

自动复盘 2023-10-20 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…