C语言进阶之路-指针、数组等混合小boss篇

news2024/11/24 10:55:11

目录

一、学习目标:

二、指针、数组的组合技能

引言

指针数组

语法

数组指针

三、勇士闯关秘籍

四、大杂脍

总结


一、学习目标:

知识点:

  • 明确指针数组的用法和特点
  • 掌握数组指针的用法和特点
  • 回顾循环等小怪用法和特点

二、指针、数组的组合技能

引言

  • 苹果
  • 苹果
  • 发霉苹果

指针数组

概念: 他是一个数组,该数组存储的多个类型相同的指针。

语法

 int *   arr[ 10 ] ;  // 整形指针数组
 char *  arr[ 10 ] ; // 字符指针数组
 float ** arr[10 ] ; // 浮点型的二级指针数组
int a  = 123 ;
int b = 456 ;
int c = 789 ;

int * arr[10] = { &a, &b ,&c }; // 定义了一个有10个元素的数组arr ,这10个元素都应该是 int 类型的地址

printf("*arr[0]:%d\n" , *arr[0] );

// arr === &a的地址 --> *arr  === &a   --> **arr === **&&a === a == 123
printf("**(arr+1):%d\n" , **(arr+1) ); 

printf("**(arr+2):%d\n" , **(arr+2) ); 

操作练习:

char * s1 = "Even";
char * s2 = "Jacy";
char * s3 = "Yilia";
char * s4 = "TieZhu";

char ** arr[4] = { &s1 , &s2 , &s3 ,&s4 };

char ***ptr = arr ;

// 使用尽可能多的方式来通过ptr 正确输出 s1 s2 s3 以及 s4 
printf("s1:%s\n" , *arr[0] );
printf("s2:%s\n" , *ptr[1] );
printf("s3:%s\n" , **(ptr+2) );
printf("s4:%s\n" , **(3+ptr) );
printf("s4:%s\n" , *3[ptr] );


// 尝试输出 s1 中的 字符 ‘E’
printf("s1:%c\n" , **arr[0] );
printf("s1:%c\n" , ***arr );
printf("s1:%c\n" , ***ptr );


// 尝试输出 s3 中的 字符 ‘Y’
printf("s3:%s\n" , **(ptr+2));
printf("s3:%c\n" , ***(ptr+2));
printf("s3:%c\n" , **(ptr[2]));

// 尝试输出 s4 中的 字符 ‘Z’
printf("s4:%s\n" , *ptr[3]);
printf("s4:%c\n" , (*ptr[3])[3]);
printf("s4:%c\n" , *((*ptr[3])+3));

数组指针

        概念: 一个指针,该指针指向一个数组。

        语法:

数组类型 (*ptr) [ 数量 ];

示例代码:

int arr[10] = {1,2,3,4,5,6,7,8,9,0};
float * f [3]; // &f 的类型是 float *(*) [3]

// int *p [10]; // 指针数组

int (*ptr) [10] ;  // 数组指针
ptr = &arr ;
// int *ptr1 = &arr ;  // &a 的类型是 : int (*)[10]

// 如何把3改成30
arr[3] = 30 ;

// ptr = &arr ;
(*ptr)[4]= 40 ;

*((*ptr)+5) = 50 ;


* ((*(ptr+1))-1) = 999 ; 


for (int i = 0; i < 10 ; i++)
{
    printf("arr[%d]:%d\n" , i , arr[i]);
}

三、勇士闯关秘籍

第一关

第二关

第三关

第四关

第五关

第六关

第七关

第八关

第九关

四、大杂脍

数组

概念:使用一篇连续的内存空间来存储一组类型相同的数据。

           可以使用它来定义一系列类型相同的数据。

语法

数据的类型   数组名 [ 元素的数量 ] ; 
int   arr_int [32] ;      // 定义了一组数据 32个(连续的内存空间)并该组数据的类型是int 类型  
float arr_float [32] ;    // 定义了一组数据 32个(连续的内存空间)并该组数据的类型是float 类型
double arr_double [64] ;  // 定义了一组数据 64个(连续的内存空间)并该组数据的类型是double 类型

char  arr_str []  = "Hello" ; // 定义了一组数据(连续的内存空间)并该组数据的类型是char 类型
                // 以上语句中没有直接说明数组中元素的数量,那么因此就必须有初始化动作,数组的大小就由初始化的数据量来决定

注意:

  • 数组在定义完成的时候,他的大小必须是已知(定义时必须明确数组的大小)。
    • 因此在定义数组的时候要么就在 【】 中括号中写明元素的数量来确定他的大小。要么就给他进行初始化。

数组名字的含义:

数组名字通常有两种含义:

        整个数组的地址:

                在定义语句中数组名表示整个数组的地址。

                在 & 取地址符中, 数组名表示整个数组的地址。

                在sizeof 运算符中 数组名表示整个数组的地址。

        首元素首地址:

                除了以上三个情况其余的都表示首元素的首地址。

数组的下标:

        概念: 数组的下标实际上是基于数组的入口地址的偏移量,偏移量的单位则是该数据则类型(指针的加减运算)。

int arr [10] = {1,2,3,4,5,6,7,8,9,0};
arr[0]   -- >  0 没有做任何偏移,因此可以访问到数组中的第0个元素  --> 数组 1 
arr[3]   -- > 数组的第3个元素 --> 数据 4 

指针:

        概念

               指针也是一个变量,只不过这种变量专门用于存储指定数据的内存地址。

        既然指针变量用于存储的是地址数据,那么指针的大小就固定下来由系统的位数决定。

                    比如32位的系统他所有的地址都是32位的数据也就是4个字节

                        64位系统他所有的地址都是64位的数据也就是8个字节

        语法:

  指向的类型  (*指针的名字) ;

int a = 123;
float f  = 2345.345;        
long l = 3245232345 ;

int * ptr_int = &a;  // 定义了一个整形指针 ptr_int  并把a的地址存入其中
float (*ptr_float) = &f ; // 定义了一个浮点指针 ptr_float  并把f的地址存入其中
long * ptr_long = &l ; // 定义了一个long指针 ptr_long  并把l的地址存入其中

指针的加减操作:

概念: 指针的加减就是基于指针当前所指向的地址进行偏移运算,而偏移量的单位则取决于指针的类型。

因此当对一个指针进行+1 或 -1 操作时加减的单位是该指针自己的类型,与它所指向的数据类型没有任何关系。

(64位系统)
char * ptr_c =  0x100000 ;
short *ptr_s =  0x100000 ;
int *ptr_i = 0x100000 ;
long * ptr_l = 0x100000 ;

ptr_c + 1 则偏移一个指针的类型char  也就是1个字节因此地址值会变成 0x100001
ptr_s + 1 则偏移一个指针的类型short  也就是2个字节因此地址值会变成 0x100002
ptr_i + 1 则偏移一个指针的类型int  也就是4个字节因此地址值会变成 0x100004
ptr_l + 1 则偏移一个指针的类型long  也就是8个字节因此地址值会变成 0x100008  

int  ** ptr_1 = 0x100000 ;
char  ** ptr_2 = 0x100000 ;
float  ** ptr_3 = 0x100000 ;

int  *** ptr_4 = 0x100000 ;
char  **** ptr_5 = 0x100000 ;
float  ***** ptr_6 = 0x100000 ;

 ptr_1  ptr_2  ptr_3  ptr_4  ptr_5  ptr_6 这些指针在+1 的时候都+ 系统的位数(64位系统) 8个字节  0x100008
  不管是多少级的指针只要超过了二级都是在+1一个地址的大小

指针数组:

                概念: 他是一个数组,该数组拥有一片连续的内存空间并该空间中存储了一组 指针数字据 (地址数据)。

                一个存储了一组指针的数组称为指针数组。

语法:

 指针的数据类型  *  (数组名字 [元素的数量]) ;
 
int *   ( arr_ptr [3] ) ={&a , &b , &c } ; // 定义了一个数组,该数组中存储了 3个元素,每一个元素都是int 类型的地址 。

注意:

        指针数组的使用与数组没有任何区别。

实例代码:

int a = 123 ;
int b = 456 ;
int c = 789 ;

// 定义了一个数组,该数组中存储了 3个元素,每一个元素都是int 类型的地址 。
int * arr_int_p [3] = {&a , &b , &c} ; // 分别把 a , b , c 的地址存入数组中

// 如何访问该数组中的所有元素
printf( "arr_int_p[0]: %p:%d \n" , arr_int_p[0] , *arr_int_p[0] );
printf( "arr_int_p[0]: %p:%d \n" , *(arr_int_p + 1) ,  **(arr_int_p + 1)  );

// ptr_int 是一个普通的整形指针,该指针存储了 &a 的地址 (二级指针)
int ** ptr_int = arr_int_p ;  // 使用二级指针来访问二维数组
printf ( "*(ptr_int + 2):%p:%d\n",  *(ptr_int + 2) , **(ptr_int + 2));

数组指针:

        概念: 他是一个指针变量,该指针变量存储的数据是一个数组类型是地址

        语法:

数组中元素的类型   (* 指针变量名) [ 数组的元素数量 ] ;

int  (*p_int)  [10] ;  // 【整形数组指针】 定义了一个指针变量  p_int ,它指向的数据的地址应该是一个整形数组的地址, 而且该数组中有10个元素
float  (*p_float)  [10] ;  // 【浮点数组指针】 定义了一个指针变量  p ,它指向的数据的地址应该是一个浮点数组的地址, 而且该数组中有10个元素

实例代码:

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

// &arr 表示整个数组的地址,因此他的类型是数组类型的地址
int (* ptr) [10] = &arr ;

// ptr = &arr   *ptr == *&arr == arr 
// arr[2] 
printf ("(*ptr)[2]:%d\n"  ,(*ptr)[2] ) ;
printf ("* ((*ptr) + 3):%d\n" , * ((*ptr) + 3) ) ;

// 使用一个一级指针来访问数组中的各项元素
int * p = arr ;
// p = arr 
// arr[5] 
printf( "p[5]:%d\n" , p[5] );
printf( "*(p + 6):%d\n" , *(p + 6) );

循环:

        概念: 使得每一段代码在特定的条件满足请跨下重复地运行。

        循环的类型:

for   是一个集成度比较高的循环结构,它包含的【初始化】、【判断】、【迭代语句】
while 是一个在条件满足的情况下执行的一个循环
do-while 是一个在执行一次代码后判断如果条件满足则执行重复代码的一个循环

for循环:

        语法:

for ( 初始化语句可以使用,逗号一次性写多个  ;   循环的判断语句   ;   循环控制变量的更新迭代 也可以是用,逗号表达式来连接多个表达式 )
{

}

注意:

while循环:

        语法:

                只要布尔表达式为真(非零) ,的情况下循环体中的代码就会被不断循环

while ( 布尔表达式 )
{
    // 循环体
    
}

do-while循环:

        语法:

先执行一次循环体中的代码,然后判断布尔表达式是否为真,如果为真则重复执行循环体中的代码。

do
{
    // 循环体
}while(布尔表达式) ;

逗号表达式

        实例:逗号表达式会从左往右依次运算,最终的值取决于最后一个表达式的值。

 int a = 123 ;
 int b = 567 ;
 int c = 789 ;
 
 int d = (a++ , ++b , ++c) ;
 printf("a:%d b:%d c:%c d:%d\n" , a  , b, c , d  );

总结

        本文介绍了C语言进阶之路上小BOSS的一些特点和打败方法,大家认真学习即可逐步突破,最终问鼎巅峰~

        本文参照 粤嵌文哥 部分课件经整理和修改后发布在C站,如有转载,请联系本人

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

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

相关文章

avamar DD组合的备份故障

证书过期导致的失败 先是显示DD页面崩了 Avamar DD 集成 — DD 在 Avamar AUI/GUI 中显示红色解决方案路径 | Dell 中国 排查了一番 尝试了重启DD 然而并没用 然后尝试更新证书 页面确实起来了 但是证书还是更新失败 确定原因还是因为版本太低而宣告失败 证书更新失败 …

自助POS收银机-亿发互联网收银解决方案助力零售业迎接数字经济挑战

零售业作为中国经济的主动脉&#xff0c;扮演着至关重要的角色。最新发布的《中国线下零售小店数字化转型报告》揭示了当前线下零售小店所面临的多重痛点&#xff0c;经营方式传统、滞后的内部管理和营销模式&#xff0c;以及缺乏消费数据等问题&#xff0c;这些痛点都指明&…

C语言 - 字符函数和字符串函数

系列文章目录 文章目录 系列文章目录前言1. 字符分类函数islower 是能够判断参数部分的 c 是否是⼩写字⺟的。 通过返回值来说明是否是⼩写字⺟&#xff0c;如果是⼩写字⺟就返回⾮0的整数&#xff0c;如果不是⼩写字⺟&#xff0c;则返回0。 2. 字符转换函数3. strlen的使⽤和…

一文读懂中间件

前言&#xff1a;在程序猿的日常工作中&#xff0c; 经常会提到中间件&#xff0c;然而大家对中间件的理解并不一致&#xff0c;导致了一些不必要的分歧和误解。“中间件”一词被用来描述各种各样的软件产品&#xff0c;在不同文献中有着许多不同的中间件定义&#xff0c;包括操…

住宅IP代理如何选择?如何识别高质量的住宅IP代理服务商

选择海外住宅IP代理时&#xff0c;了解其评估标准、优势和实际应用至关重要。住宅IP代理不同于其他类型的代理&#xff0c;它提供更高的匿名性和较低的封禁风险&#xff0c;适用于多种网络场景。本指南将深入分析如何根据服务质量、速度、安全性和客户支持等关键因素&#xff0…

数学建模之相关系数模型及其代码

发现新天地&#xff0c;欢迎访问小铬的主页(www.xiaocr.fun) 引言 本讲我们将介绍两种最为常用的相关系数&#xff1a;皮尔逊pearson相关系数和斯皮尔曼spearman等级相关系数。它们可用来衡量两个变量之间的相关性的大小&#xff0c;根据数据满足的不同条件&#xff0c;我们要…

uniapp 微信小程序连接蓝牙卡死 uni.onNeedPrivacyAuthorization

解决方法&#xff0c;需要同意隐私保护协议&#xff0c;否则不能开启蓝牙权限和定位权限&#xff0c;会导致连接蓝牙失败

【Vue】使用cmd命令创建vue项目

上一篇&#xff1a; node的安装与配置 https://blog.csdn.net/m0_67930426/article/details/134562278?spm1001.2014.3001.5502 目录 一.创建空文件夹专门存放vue项目 二. 查看node , npm 和vue脚手架的版本 三.安装vue脚手架 四.创建vue项目 五.运行项目 一.创建空文件…

在Windows11(WSL)中如何迁移Docker

前言&#xff1a; 在Windows 10中Docker是默认安装到WSL中的&#xff0c;而安装到WSL中的任意分发版都是默认放在C盘中的。这样会让我们的C盘资源极度紧张&#xff0c;而且也限制了Docker的镜像数量。 迁移步骤 假设我有一个临时目录“D:\docker”用来存放临时文件&#xff0c;…

基于ssm vue的社区互助平台源码和论文

摘 要 随着社区互助规模的不断扩大&#xff0c;社区互助数量的急剧增加&#xff0c;有关社区互助的各种信息量也在不断成倍增长。面对庞大的信息量&#xff0c;就需要有社区互助管理来提高社区互助管理工作的效率。通过这样的系统&#xff0c;我们可以做到信息的规范管理和快速…

【从零开始学习JVM | 第一篇】快速了解JVM

前言&#xff1a; 在探索现代软件开发的丰富生态系统时&#xff0c;我们不可避免地会遇到一个强大而神秘的存在——Java虚拟机&#xff08;JVM&#xff09;。作为Java语言最核心的组成之一&#xff0c;JVM已经超越了其最初的设计目标&#xff0c;成为一个多语言的运行平台&…

nacos启动报错 java.lang.RuntimeException: [db-load-error]load jdbc.properties error

以standalone mode sh startup.sh -m standalone 为例子 启动nacos 报错&#xff1a; Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcatat org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(To…

【九】linux下部署frp客户端服务端实践(内网穿透)

linux下部署frp客户端服务端实践 简介&#xff1a; 今天有一个这样的需求&#xff0c;部署在公司内部局域网虚拟机上的服务需要在外网能够访问到&#xff0c;这不就是内网穿透的需求吗&#xff0c;之前通过路由器实现过&#xff0c;现在公司这块路由器不具备这个功能了&#x…

『亚马逊云科技产品测评』活动征文|基于亚马逊EC2云服务器配置Nginx静态网页

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道 亚马逊EC2云服务器&#xff08;Elastic Compute Cloud&#xff09;是亚马…

网络安全威胁——中间人攻击

中间人攻击 1. 定义2. 中间人攻击如何工作3. 常见中间人攻击类型4. 如何防止中间人攻击 1. 定义 中间人攻击&#xff08;Man-in-the-Middle Attack&#xff0c;简称MITM&#xff09;&#xff0c;是一种会话劫持攻击。攻击者作为中间人&#xff0c;劫持通信双方会话并操纵通信过…

生产环境_从数据到层级结构JSON:使用Spark构建多层次树形数据_父子关系生成

代码补充了&#xff01;兄弟萌 造的样例数据 val data Seq(("USA", "Male", "Asian", "Chinese"),("USA", "Female", "Asian", "Chinese"),("USA", "Male", "Bl…

flask web学习之flask与http(一)

文章目录 一、请求响应循环二、HTTP请求1. 请求报文2. request对象3. 在flask中处理请求3.1 路由匹配3.2 设置监听的http方法3.3 URL处理 三、请求钩子 一、请求响应循环 每一个web应用都包含这种处理方式&#xff0c;请求-响应循环&#xff1a;客户端发出请求&#xff0c;服务…

Linux【缓冲区】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;缓冲区是什么&#xff1f;为…

23、pytest通过skip跳过测试用例

官方实例 # content of test_skip.py import pytest import syspytest.mark.skip(reason"no way of currently testing this") def test_the_unknown():passdef valid_config():return Falsedef test_function():if not valid_config():pytest.skip("unsupport…

毕业论文及各种办公文件word页码的设置大全

当我们在写论文或者报告的时候&#xff0c;经常需要我们给文档设置页码&#xff0c;用于页码统计&#xff0c;也方便后期的查阅和阅读&#xff0c;但是经常遇到特殊的要求或者情况&#xff0c;比如删除了某个页的页码&#xff0c;那么整个文档目录的页码就会全部被删除&#xf…