C语言要点细细梳理(下)

10. 运算符补充

10.1 位运算

位运算符:<< >> & | ~ ^

  • << >> :按位左移右移,移出去的数直接丢掉,符号不动
    在这里插入图片描述

  • &:按位与

  • |: 按位或

  • ~:按位非

  • ^:按位异或

位运算对应CPU最底层的门电路,运算速度非常快,这也是位运算的优点

利用位运算符输出一个整数的二进制形式
int main(){
    unsigned a = 0XFFFFFFFF;
    unsigned length = sizeof(a)*8;
    unsigned background = 1<<(length-1);
    for (int i = 0; i < length; ++i) {
        unsigned shifted_a = a<<i;
        unsigned temp = shifted_a & background;
        unsigned result = temp>>(length-1);
        printf("%u ",result);
    }
    return 0;
}

在这里插入图片描述

10.2 三元表达式

表达式1?表达式2:表达式3

  • 如果表达式1取非0,则整个式子替换成表达式2
  • 如果表达式1取0,则整个式子替换成表达式3

三元表达式可以嵌套使用

运算符优先级
  • 三目 > 赋值类 > 逗号
  • 其他所有运算符 > 三目

10.3 逗号表达式

  • 逗号运算符是C语言优先级最低,即用逗号分隔的若干个子表达式
  • 效果:从左至右依次执行各个子表达式
  • 完成替换值:所有子表达式运算完后,最右侧的子表达式
    在这里插入图片描述

10.4 switch语句

  • 如果没有break,在执行完成对应case后会接着执行
  • 注意巧用break

10.5 维持terminal(阻退)

  • 思考:编译出来的 xxx.exe 文件是不是从来没双击打开过?为什么
  • 因为双击打开意味着将打开一个独立窗口,程序结束则窗口自动关闭,无法查看输出
  • 所以通过终端执行 .xxx.exe 来启动,程序结束后终端还在

两种解决方式:

  1. 两个getchart()
  2. system(“pause”);

在这里插入图片描述

11. 指针

11.1 地址和指针

注意,指针的值是一个地址

  • 程序运行时,数据存放在内存中(PCB)
int n=4;			//&:取变量指针,包括地址和解释方式
int *p=&n;			//*:间接引用符号,表示按照该指针指向类型解读该指针记录的地址上的数据
*p=10;				//int *:数据类型,表示指向int的指针 
printf("%d",*p);

11.2 指针的四个性质

  • 数据 = 地址 + 类型:变量名同时帮我们维护了这两者,我们直接按名用就行,但指针是对这两个信息进行解构,使对数据的处理更加灵活:
  1. 指针本身是一个变量,其值是一个地址,如果要打印指针的值,即打印地址的值,占位符应该是%p,表示地址
  2. 指针本身的类型,比如 i n t ∗ p ; int *p; intp其指针本身的类型是 i n t ∗ int * int,指针p认为它所指向的地址存放的是一个int类型数据
  3. 指向的类型,比如 i n t ∗ p ; int *p; intp其指针指向的类型是是 i n t int int
  4. 指向的值,*运算符会按照指针记录的地址和指针类型指明的类型表示方式,解读出该位置的值
  • 指针通过值记录一个数据的地址类型表示解读方式实现了间接访问数据

在这里插入图片描述
在这里插入图片描述

11.3 指针传参

  • 参数占用空间大,且函数对参数的使用过程中不进行修改,那么靠拷贝传参空间复杂度过大
  • 拷贝传参,形参仅在函数内部有效,无法对实际参数造成影响
指针传参的特点
  • 指针传参:函数的参数是指针,调用时给它传递的参数是指针
  • 实际上指针传参和按值传参并无本质区别,就是指针的按值传参
    在这里插入图片描述

11.4 二级指针

指针的本质也是一个变量,也有自己存放的地址,二级指针与一级指针的关系=一级指针与变量的关系

11.5 指针与数组

数组的特性
  1. 元素类型相同
  2. 内存地址连续(顺序存储)
  3. 下标的本质是偏移量
指针的特性
  1. 记录数据地址
  2. 记录数据类型

在这里插入图片描述

指针偏移运算
  • 指针偏移运算以其指向的数据类型大小为单位

在这里插入图片描述

  • 指针运算的结果:
    • ①地址按其类型为单位变更
    • ②仍然得该类型指针
  • *(p +i)等价于 p[i],因此数组索引方式 a[i] 本质就是指针运算 + 间接引用

在这里插入图片描述

需要时刻注意,指针表示单元格数,不是字节数

在这里插入图片描述

12. 动态内存分配

12.1 C程序内存模型

  • 内存模型:描述程序在运行时,如何组织和利用自己的内存空间

在这里插入图片描述

12.2 malloc与free

12.2.1 动态内存分配

  • 发生在堆区:即堆区内存就是设计来给程序动态地 申请-使用-归还 的
  • malloc:申请一块指定大小的堆区内存,若成功返回指向其首地址的指针
  • free:归还指针所指向的堆区内存
  • 使用malloc和free需要包括头文件
#include <stdlib.h>
//用malloc申请4字节的堆区内存,得到一个void*指针,强转成int*
int *ptr;
ptr = (int *)malloc(4);
*ptr = 10;
printf("%d",*ptr);
free(ptr);
//通过malloc和sizeof申请一个动态数组
int *ptr;
ptr = (int*)malloc(3*sizeof(int));
ptr[0]=1;
*(ptr+1)=2;
ptr[2]=3;
printf("%d",*ptr);//输出1
free(ptr);
堆区内存碎片

malloc分配内存空间的过程是随机散乱的,可能在堆区产生若干内存碎片

12.2.2 动态内存和数组

大多数情况下,申请到的动态堆内存都是用于实现类似动态数组

动态内存与数组的异同:
相同点:

  • 数组和动态内存得到的空间都是完整的、连续的、定长的(分配后无法改变长度)

不同点:

  • 数组是变量,指定类型,由编译器维护生命周期和类型
  • 堆内存是自行管理、按需分配的,没有类型的限制,需要申请者通过指针来解释地址存的内容
小端机器的特点

高位地址存放高位数据,低位地址存放低位数据

12.3 内存溢出和内存泄漏

内存溢出——内存空间不足
内存泄漏——malloc但是不free,增大了内存溢出的概率“

“借了东西为什么不还~~”——《你的背包》
在这里插入图片描述

  • 申请到内存堆空间,一定要找地方存起来,如果存放分配空间的地址被覆盖,原来申请的空间就找不到了,造成内存泄漏

13. 指针综合

13.1 数组类型与数组名

数组名支持的操作

在这里插入图片描述

数组名与指针的差异

在这里插入图片描述

  • 表明数组名一定不是指针,因为指针存放地址,占用8字节,而数组名占用空间就是数组所占内存字节数
编译器对数组名的处理——数组名a其实通常为&a[0]
int a[5]={1,2,3,4,5};
  • 回忆数组本质:自定义数据类型,如 int[5]表示“元素个数为5的整型数组类型
  • 数组名(如a)就是数组类型(如int [5])的一个变量,但编译器对数组名会有一特殊处理:
    • 除以下两种情况外,数组名 a都会被偷偷转变为 &a[0]:
      1. sizeof(a)被转化为sizeof(int [5])
      1. &a——&运算符作用于数据上相当于取得一个指针(地址),作用在a上得到四个属性为:

在这里插入图片描述
因此,&a其实是得到一个数组指针

13.2 数组指针与指针数组

13.2.1 数组指针——是个指针【int (*p)[5]】(本节进入指针的深水区,注意仔细体会)

  • 对数组名取地址得到一个数组指针——指向数组的指针
    int a[5]={1,2,3,4,5},b[5]={6,7,8,9,0};
    int (*p)[5]=&a;
    printf("%d,",(*p)[2]);//3
    p=&b;
    printf(" %d",(*p)[2]);//8

上述p的三种错误写法:

  • p[2]
  • *(p+2)
  • *p[2]

p指向的是一个int [5]地址的指针
注意: p [    ] p[\ \ ] p[  ] p . x p.x p.x p − > x p->x p>x中的 [    ] [\ \ ] [  ]操作、   . \ .  .操作和   − > \ ->  >操作的优先级均高于*和&,因此 ∗ p [ 2 ] = ∗ ( p [ 2 ] ) *p[2]=*(p[2]) p[2]=(p[2]),而 p [ 2 ] p[2] p[2]是错误写法

t e m p l a t e   ( ∗ p ) [ N ] template\ (*p)[N] template (p)[N]含义是,p是一个指向 t e m p l a t e   [ N ] template\ [N] template [N]类型的指针: t e m p l a t e   ( ∗ ) [ N ] template\ (*)[N] template ()[N]
在这里插入图片描述

13.2.2 指针数组——是个数组【int *p[5]】

  • 定义一个数组,存储指定数量个指针数据:存储指针的数组

注意:区分指针数组和数组指针定义的核心关键:后缀运算符优先级大于前缀运算符

t e m p l a t e ∗ p [ N ] template *p[N] templatep[N]含义是,p是一个存储了N个 t e m p l a t e   ∗ template\ * template 类型指针的数组
在这里插入图片描述

13.3 指针常量和常量指针

  • 此处常量指的是不变量(const)
  • 指针常量和常量指针都是指针
  • 区别在于是自己不能被赋值,还是其间接引用不能被赋值
  • 先读在前,在前不变

在这里插入图片描述

13.4 字符串与字符数组

三大常考点:

  1. 字符串由char*表示
  2. 字符串结束符是’\0’
  3. 不能修改字符串常量的内容

13.4.1 字符串

  • 字符串:一串连续的字符(字节)
  • 双引号内部的字符串,其实是字符串常量,存放在常量区(被操作系统限定),不可以修改 ,如果修改会报运行时错误
    在这里插入图片描述
    尝试修改的示例:
    在这里插入图片描述

Process finished with exit code -1073741819

遇到 “Process finished with exit code -1073741819 (0xC0000005)” 错误通常表示程序发生了访问违例(Access Violation)错误。这种错误通常是由于访问无效的内存地址或访问未初始化的变量导致的。

13.4.2 字符数组

  • 字符数组:连续排列的字符变量,存放在栈区
  • 初始化时,可以将常量区的字符串常量copy到字符数组中进行初始化,这种初始方法可以不考虑字符串末尾的’\0’
  • 另一种初始化方法是对字符数组元素进行逐个赋值,但是这种方法需要自己补充’\0’,如果没有’\0’就只是一个单纯的字符数组,并不是字符串

在这里插入图片描述

字符数组与字符串的区别
  • 字符串必须有’\0’作为结尾
  • 字符数组可以存放字符串,但是也可以不存’\0’,做一个单纯的字符数组

13.5 字符串库函数

引入头文件:

#include <string.h>
  • 首先明确,C语言没有一个类型叫“字符串”,字符串就是用char*表示的
  • 以下函数的参数都是一个或两个 char* 数据

在这里插入图片描述

sizeof

对与字符数组,计算长度时如果末尾有’\0’,需要计入sizeof,有两种情况:

char a[]="a";//sizeof为2,strlen为1
char b[]={'a'};//sizeof为1,不是字符串strlen为0

在这里插入图片描述

strcpy
  • strcpy:s1=>“bb\0aa\0”

在这里插入图片描述

  • 延申1:malloc获得的堆区内存完全可以当字符数组用,用char*操作即可
  • 延申2:如果strcpy,strcat等函数中的两个字符串有重叠怎么办?
    【内存重叠之strcpy/strncpy/strcat/strncat和memcpy】
    【strcpy的实现,以及内部重叠问题的解决。memcpy和memove的区别。】

13.6 结构体指针

访问结构体成员的两种方式
  1. 直接使用结构体数据(如变量)的成员,使用**.运算符**
  2. 若使用指针指向一个结构体数据,可使用**->运算**符访问其成员

在这里插入图片描述

  • (*p->p).a.f是从堆区中申请的,没有进行初始化操作,因此应该是随机数

14. 文件输入输出

14.1 文本文件

14.1.1 什么是文件

  • 任何外部数据源都是文件(于操作系统而言)
  • 和运行的程序(内存数据)不同,文件中的数据是持久化的,断电也存在
  • 但本质仍是数据(二进制字节块/字节流)

14.1.2 标准IO与文件IO

  • 我们熟悉使用 printf 和 scanf 等库函数用以控制台IO
  • 控制台本质也是一个外部数据源,换言之文件I0和控制台I0是类似的
  • 即学习文件IO就是学习一系列C语言文件操作的函数的用法/效果

在这里插入图片描述

14.1.3 文本文件IO

  • 通过 fopen 函数用指定模式打开指定路径的文件,获得一个 FILE*指针
  • 文件打开模式包括:①权限 ②方式,以字符串的形式传递给 fopen 函数
14.1.3.1 文件打开与检查:fopen
  • 文件是外存上的实体,在C程序中用一个结构体指针(FILE*)(文件指针)表示它
  • 类比:同学们(文件)把学生卡(文件指针)都交给老师进行抽奖

在这里插入图片描述

14.1.3.2 文件路径
  • 相对路径:以程序执行路径(编译后生成的.exe文件所在路径)为基准的路径

在这里插入图片描述

  • 绝对路径:以操作系统根目录为基准的路径

在这里插入图片描述

14.1.3.3 文件打开模式
  • r:read,读
  • w:write,写
  • a:appand,追加

在这里插入图片描述

读写权限

在这里插入图片描述

读写方式

在这里插入图片描述

14.1.3.4 从文本文件中读:fscanf
  • 从文本文件中读内容等效于从控制台中读取用户输入的相同内容
  • 只不过,使用 fscanf函数并指定文件指针

在这里插入图片描述

14.1.3.5 向文本文件中写:fprintf
  • 往文本文件中写内容等效于往控制台输出内容
  • 只不过,使用 加fprintf函数并指定文件指针

在这里插入图片描述

14.1.3.6 判断是否读取至文件末尾:feof
  • 文件指针随着读写而在文件中不同位置前后移动
  • 在读文件时,文件指针移动到文件末尾就意味读取完成了文件所有内容
  • 使用专门的函数 feof 进行此判断
    在这里插入图片描述
14.1.3.7 往文本文件中追加
  • 往文本文件中追写内容需要在打开模式字符串中包含字母
  • 会从文件的原有内容的最未尾后继续写入
  • 追写模式实质是打开文件后,将文件指针置于文件未尾

在这里插入图片描述

其他注意点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

14.1.4 二进制文件IO

  • 文本文件:对数据进行ASCII编码后,按字节逐字符写入/读取
  • 二进制文件:直接将内存二进制数据整体搬入文件,要解读需要知道其特定格式

在这里插入图片描述

二进制文件读写:fread、fwrite
  • 直接把二进制文件读写理解成字节块搬家即可,fwrite搬进去,fread搬出来
    在这里插入图片描述
    调换两行,会导致读出来的东西与写入顺序不一致。

在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS使用CoreML运用小型深度神经网络架构对图像进行解析

查找一个图片选择器 我用的是ImagePicker 项目有点老了&#xff0c;需要做一些改造&#xff0c;下面是新的仓库 platform :ios, 16.0use_frameworks!target learnings dosource https://github.com/CocoaPods/Specs.gitpod ImagePicker, :git > https://github.com/KevinS…

基于VUE实现的餐厅经营游戏项目源码

WebMOOC 餐厅游戏 项目介绍 实现了一个类游戏的餐厅经营模拟&#xff0c;涉及的前端知识有移动端 HTML 页面布局及样式实现。实现了厨师、顾客等角色的关键操作&#xff0c;完成从顾客等位、点菜、烹饪、用餐、支付的一系列状态变更的数据、信息、交互、展现的变化及处理。 …

巨控560:走向国际,我们的设备如何拥抱远程控制技术?

走向国际&#xff0c;我们的设备如何拥抱远程控制技术&#xff1f; 描述&#xff1a;随着国内设备走向国际市场&#xff0c;客户需求的多样性和不确定性大大增加。本文将深入探讨在这一背景下&#xff0c;是否有必要为我们的设备加装远程PLC控制模块&#xff0c;以及如何应对频…

分布式系统架构中的相关概念

1.1、衡量网站的性能指标 响应时间&#xff1a;指执行一个请求从开始到最后收到响应数据所花费的总体时间。并发数&#xff1a;指系统同时能处理的请求数量。 并发连接数&#xff1a;指的是客户端向服务器发起请求&#xff0c;并建立了TCP连接。每秒钟服务器连接的总TCP数量请…

基于SSM+Jsp+Mysql的图书仓储管理系统

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

ospf的路由计算

LSA是链路状态信息&#xff08;描述接口信息&#xff09;&#xff0c;路由器将接口信息发给其他路由器&#xff0c;LSA有6个分类&#xff0c;1&#xff0c;2类描述区域内信息&#xff0c;3类是区域间的&#xff0c;5类是外部路由&#xff0c;4类是对5类的补充&#xff0c;7类是…

企微知识库优缺点解析:如何让其效益最大化

企业搭建企微知识库&#xff0c;作为企业内部知识的集中存储和共享平台&#xff0c;为企业带来了很多便利。但是&#xff0c;任何事物都有其两面性&#xff0c;企微知识库也不例外。今天我们就来详细探讨搭建企微知识库的优点和缺点&#xff0c;如何在使用企微知识库时使其发挥…

【群晖】NASTOOL-自动化处理影音视频工具

【群晖】NASTOOL-自动化处理影音视频 本文主要从获取、部署、使用、配置等方面进行手把手教学如何使用nastool工具进行影音视频自动化处理。从此靠别繁琐的网上各个网址找资源-下载-复制-改名-刮削等操作。 准备 DSM 7.1 &#xff08;我使用的是群晖 7.1 系统&#xff0c;不管…

【一站式学会Kotlin】第一节 kotlin 介绍

作者介绍&#xff1a; 百度资深Android工程师T6&#xff0c;在百度任职7年半。 目前&#xff1a;成立赵小灰代码工作室&#xff0c;欢迎大家找我开发Android、微信小程序、鸿蒙项目。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默。给大家…

并发编程之线程池的应用以及一些小细节的详细解析

线程池在实际中的使用 实际开发中&#xff0c;最常用主要还是利用ThreadPoolExecutor自定义线程池&#xff0c;可以给出一些关键的参数来自定义。 在下面的代码中可以看到&#xff0c;该线程池的最大并行线程数是5&#xff0c;线程等候区&#xff08;阻塞队列)是3&#xff0c;即…

【Java集合进阶】list常见的方法和五种遍历方式数据结构

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏…

03-04java基础之数据类型举例

1、需要特殊注意的数据类型举例 1&#xff09;定义float类型&#xff0c;赋值时需要再小数后面带f float num11.2f; System.out.println(num1);2&#xff09;定义double类型&#xff0c;赋值时直接输入小数就可以 3&#xff09;另外需要注意&#xff0c;float类型的精度问题…

修改element-ui table组件展开/收起图标、支持点击行展开/收起、隐藏不可展开行得图标

Element中table默认支持的&#xff0c;展开和收起功能&#xff0c;如下&#xff1a; 针对表格的展开收起&#xff0c;本文改造的主要有3点&#xff1a; 1、修改展开/收起的图标&#xff1b; 2、对于不支持展开/收起的行&#xff0c;隐藏图标&#xff1b; 3、点击行&#xff0…

AcWing---转圈游戏---快速幂

太久没写快速幂了... 这是一道数学题orz&#xff0c;能看出来的话答案就是 &#xff0c;但是很大&#xff0c;同时还要mod n&#xff0c;直接用快速幂即可。 快速幂模版&#xff1a; long long int power(long long int a,long long int b,long long int mod){long long int r…

c++20协程详解(一)

前言 本文是c协程第一篇&#xff0c;主要是让大家对协程的定义&#xff0c;以及协程的执行流有一个初步的认识&#xff0c;后面还会出两篇对协程的高阶封装。 在开始正式开始协程之前&#xff0c;请务必记住&#xff0c;c协程 不是挂起当前协程&#xff0c;转而执行其他协程&a…

Shell脚本之基本语法

目录 一、变量定义 变量命名规则&#xff1a; 变量的赋值&#xff1a; 只读变量&#xff1a; 删除变量&#xff1a; 二、变量的类型 自定义变量&#xff1a; 环境变量&#xff1a; 位置参数&#xff1a; 预定义变量&#xff1a; 三、键盘输入 四、数值运算 为什么…

Failed to resolve import “Home/components/HomeNew.vue“. Does the file exist?

错误信息 [plugin:vite:import-analysis] Failed to resolve import "/apis/home.js" from "src/views/Home/components/HomeNew.vue". Does the file exist? 错误原因 路径错误 解决方法

mysql-FIND_IN_SET包含查询

如图所示&#xff0c;需要查询字段ancestorid中包含14的所有数据&#xff0c;使用FIND_IN_SET即可实现&#xff0c;不需要使用模糊查找like 示例sql&#xff1a; SELECT * FROM mt_fire_template WHERE FIND_IN_SET(14,ancestorid) 结果

安装Pillow库的方法最终解答!_Python第三方库

安装Python第三方库Pillow 我的环境&#xff1a;Window10&#xff0c;Python3.7&#xff0c;Anaconda3&#xff0c;Pycharm2023.1.3 pillow库 Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能&#xff0c;让我们可以轻松地读取和保存图像、创建缩略图和合并到…

LeetCode-94. 二叉树的中序遍历【栈 树 深度优先搜索 二叉树】

LeetCode-94. 二叉树的中序遍历【栈 树 深度优先搜索 二叉树】 题目描述&#xff1a;解题思路一&#xff1a;递归解题思路二&#xff1a;迭代解题思路三&#xff1a;0 题目描述&#xff1a; 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1…