C语言进阶

2023-05-16

C语言进阶

  • 数据操作
      • 1 数据修饰 auto、static、register、const、volatile
      • 2 大端模式、小端模式
  • 内存操作
      • 1 动态内存管理(堆区 heap) malloc、calloc、realloc、free
      • 2 GCC对C的扩展:内存对齐 __attribute__、aligned()、packed()、at
  • 文件操作
      • 1 文件 I/O 库
        • 1.1 文件描述符
        • 1.2 读写操作(open 、close 、write 、read)
        • 1.3 文件 I/O 内核缓冲
      • 2 标准I/O 库
        • 2.1 FILE 指针
        • 2.2 读写操作(fopen 、fclose 、fwrite 、fread)
        • 2.3 标准 I/O 的 stdio 缓冲
  • 不常见的函数
      • 终止进程 exit()、_exit()

数据操作

1 数据修饰 auto、static、register、const、volatile

  • auto

auto关键字 修饰局部变量

auto修饰局部变量,标志这个局部变量是自动局部变量,自动局部变量分配在栈上。(也就是说如果不初始化,那么值就是随机的)

auto的局部变量就是默认定义的普通的局部变量,省略了auto关键字而已,

  • static
static关键字可以修饰:局部变量、全局变量、函数
static修饰后改变了什么?
1.改变了生存周期 
2.改变了作用域 

static修饰不同对象时的作用:

1、局部变量:
局部变量就是在函数内定义的变量,普通的局部变量,生存周期是随着函数的结束而结束,
当用static修饰后,静态局部变量的生存周期就是当程序结束才会结束。
改变其生存周期的原因是被static修饰的局部变量被存放在.bss段或者.data段,而普通的局部变量是存放在栈上的。
总结:改变了生存周期,但是没有改变其作用域。

2、全局变量:
全局变量用static修饰改变了作用域,没有改变生存周期。
普通的全局变量是可以被其他的.c文件引用的,静态全局变量就只能被定义该全局变量的.c文件引用。
这样其他的文件就不能通过extern的方式去访问,这样主要是为了数据安全。
总结:改变其作用域,没有改变生存周期。

3、函数:
函数用static修饰,改变了作用域。
和静态全局变量一致

  • register

register修饰的变量(一般是全局变量),编译器会尽量将它分配在寄存器中。(平时分配的一般是在内存中的)。
通过改善这个变量的访问效率可以极大地提升运行效率。读写效率会更高。
所以register修饰的变量用在那种变量被反复高频率的作用,

  • const

const限定一个变量不允许被改变,产生静态作用。

可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。

  • volatile

volatile 关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问

2 大端模式、小端模式

大端字节存储模式 :
是指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中

小端字节存储模式。
是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中

以0x1234为例进行说明。

在这里插入图片描述

内存操作

在一个C语言程序中,能够获取的内存就是三种情况:栈(stack)、堆(heap)、静态存储区
在这里插入图片描述

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

  • 静态存储区

由 操作系统 分配 和 使用,有 .bss段 和 .data段组成,可读可写。

.data段(数据段)

已初始化的全局变量、静态变量存放在.data段。
.data段占用可执行文件空间,其内容有程序初始化。

.bss段
未初始化的全局变量、静态变量 和 初始化为0的全局变量、静态变量存放在.bss段。
.bss段不占用可执行文件空间,其内容由操作系统初始化。

  • 栈 stack

函数执行时,函数的形参以及函数内的局部变量,分配在栈区,函数运行结束后,形参和局部变量去栈(自动释放)。
编译器在需要的时候分配,不需要时自动清除

1 动态内存管理(堆区 heap) malloc、calloc、realloc、free

开辟内存的函数 

1void* malloc(size_t size); 
 如果开辟成功,返回一个指向开辟好空间的指针。
 如果开辟失败,则返回一个NULL指针,所以使用malloc,要对返回值进行检查。 

2void* calloc(size_t num,size_ size);
 函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。
 与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全03、realloc 
 原本申请的空间不够,通过这个函数创建新的空间

释放动态开辟的内存

void free(void* ptr); 

2 GCC对C的扩展:内存对齐 attribute、aligned()、packed()、at

GNU使用__attribute__选项来设置我们想要的内存字节对齐大小。__attribute__选项不属于标准C语言,它是GCC对C语言的一个扩展用法。

GCC支持用__attribute__为变量、类型、函数、标签制定特殊属性。

大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。

  • aligned

该属性设定一个指定大小的对齐格式(以字节 为单位)

struct p
 {
  int a;
  char b;
  short c;
 }__attribute__((aligned(4))) pp;

sizeof(a)+sizeof(b)+sizeof(c)=4+1+1=6<8 所以sizeof(pp)=8

struct m
 {
  char a;
  int b;
  short c;
 }__attribute__((aligned(4))) mm;

sizeof(a)+sizeof(b)+sizeof(c)=1+4+2=7

a 后面需要用 3 个字节填充 才能和 b 是 4 个字节 一致 
所以 a 占用 4 字节, b 占用 4 个字节,而 c 又要占用 4 个字节。所以 sizeof(mm)=12

  • at

attribute( at(绝对地址) )的作用分两个,一个是绝对定位到Flash,另个一是绝对定位到RAM。

定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等

const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};
const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;
定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量

//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.
u8 USART2_RX_BUF[USART2_REC_LEN] __attribute__ ((at(0X20001000)));

1、绝对定位不能在函数中定义,局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。
2、定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。

文件操作

1 文件 I/O 库

文件 I/O 指的是对文件的输入 / 输出操作,说白了就是对文件的读写操作
文件 I/O 是系统调用

1.1 文件描述符

文件描述符:是一个非负整数,是一个文件句柄,是与对应的文件绑定

文件描述符的分配:为没有被使用的且最小的非负整数

系统定义的文件描述符:0 1 2( 标准输入、标准输出、标准错位 )

1.2 读写操作(open 、close 、write 、read)

1open("路径""flag方式")
   open("路径""flag方式""权限")

flag方式

O_RDONLY:  只读方式
O_WRONLY:  只写方式
O_RDWR:    可读可写方式
O_CREAT:   不存在就创建
O_EXCL:    和 O_CREAT 搭配使用

权限

如果使用 O_CREAT,则需要加入第三个参数,设置文件的权限
 
2、close(文件描述符) 

3、write(文件描述符,"写入的数据""数据大小"4、read(文件描述符,"存储读取数据的缓冲区""数据大小"

1.3 文件 I/O 内核缓冲

调用 write() 只是将 字节数据拷贝到了 内核空间的缓冲区 ,拷贝完成之后函数就返回了, 在后面的某个时刻,内核会将其缓冲区中的数据写入(刷新)到磁盘设备中,所以由此可知,系统调用 write() 与磁盘操作并不是同步的,write()函数并不会等待数据真正写入到磁盘之后再返回。

  • 控制文件 I/O 内核缓冲的系统调用
1fsync()函数  文件的内容数据和元数据写入磁盘,只有在对磁盘设备的写入操作完成之后,fsync()函数才会返回

2fdatasync()函数 并不包括文件的元数据	

3sync()函数 将所有文件 I/O 内核缓冲区中的文件内容数据和元数据全部更新到磁盘设备中

2 标准I/O 库

标准C库中,用于文件I/O操作的库函数,叫做 标准I/O库

在这里插入图片描述

2.1 FILE 指针

FILE 指针的作用相当于文件描述符,只不过 FILE 指针用于标准 I/O 库函数中、而文件描述符则用于文件I/O 系统调用中

2.2 读写操作(fopen 、fclose 、fwrite 、fread)

  • fopen()
1fopen("路径""flag方式")

r  只读方式打开   O_RDONLY
r+ 可读可写方式   O_RDWR
w  只写方式打开(无文件则创建)  
w+ 可读可写方式打开(无文件则创建)
a  只写方式打开(在文件尾写入,无文件则创建)  
a+ 可读可写方式打开(在文件尾写入,无文件则创建)
 
2、fclose(FILE 指针) 

3、fwrite(”写入数据“,每个字节大小,总大小,FILE 指针)
  返回读取到的数据项的数目

4、fread(读出存储的数据缓冲区,单字节大小,总字节大小,FILE 指针)
  返回写入的数据项的数目

5、fseek(FILE 指针,偏移量,SEEK_SET)
  SEEK_SET 文件开头处
  SEEK_END 文件末尾处

2.3 标准 I/O 的 stdio 缓冲

标准 I/O 在应用层维护了自己的缓冲,称为stdio 缓冲

  • 控制 stdio 缓冲
1setvbuf(FILE 指针,buf,缓冲类型,大小) 
int setvbuf(FILE *stream, char *buf, int mode, size_t size);

缓冲类型:
_IONBF 无缓冲,将立即调用文件 I/O 操作 write()或者 read()

_IOLBF 行缓冲,遇到换行符"\n"时,标准 I/O 才会执行文件
       标准输入和标准输出默认采用的就是行缓冲模式 

_IOFBF 全缓冲 在填满 stdio 缓冲区后才进行文件 I/O 操作(read、write)。
       普通磁盘上的常规文件默认全缓冲模式。

2fflush(stdout)
	强制刷新将输出到 stdio 缓冲区中的数据写入到内核缓冲区
	

不常见的函数

终止进程 exit()、_exit()

这个参数用来表示进程终止时的状态,0表示正常终止,其余 表示非正常终止,

1void exit(int status)
exit()是C语言库函数 头文件 <stdlib.h>

2void _exit(int status)
 _exit()**系统调用函数**

在这里插入图片描述

  • exit()、return()的区别

exit()是一个库函数, return()是C语言的语句
exit() 函数最终会进入到内核,把控制权交给为内核,最终由内核去终止进程。
return并不会进入到内核,它只是一个main函数返回,返回到它的上层调用把控制权交给他的上层调用,最终由上层调用终止进程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言进阶 的相关文章

  • C++11之lambda函数

    最近一直在看mesos的源代码 xff0c mesos中用到了很多C 43 43 11的新特性 xff0c lambda函数就是其中的一个 对于lambda函数简单的来说就是java中的匿名函数 语法定义 capture paramente
  • C++中两个类互相包含

    今天突然想起一个C 43 43 的问题 xff0c 如果一个类A包含类B的实例 xff0c 而实例B也包含另一个类A xff0c 这种方式的代码应该怎么写 xff0c 按照一般的开发者的想法的代码如下 xff1a 文件A h span cl
  • 命名空间

    命名空间的作用 命名空间是为了防止名字冲突提供更加可控的机制 命名空间分割了全局命名空间 xff0c 其中每一个命名空间是一个作用域 命名空间的定义 命名空间由三部分组成 xff0c 分别是namespace 空间名字和一系列由花括号括起来
  • STL中的swap函数

    swap函数执行会调用容器内数据类型的 xff0c 拷贝构造和赋值函数调用 对自定义类型使用STL algorithm中的swap函数 xff0c 会调用自定义的类型的拷贝构造函数一次 赋值函数两次 xff1b 自定义类型中没有定义那么就会
  • C++11之POD类型

    什么是POD类型 POD的全称叫做Plain Old Data xff0c 简单讲就是一个类或者一个结构体通过二进制拷贝之后还能保持其不变 xff0c 那么这个类型就是POD类型 什么类型属于POD类型 当一个类型具有平凡的定义和标准布局这
  • C++11之初始化成员变量

    C 43 43 98中的成员变量初始化 在声明类的时候 xff0c 对于静态类型并且是常量类型 xff0c 同时是枚举或者是整型的变量可以使用 61 在声明时初始化 对于不符合上述要求的静态变量可以在类外使用 61 进行初始化对于非静态类型
  • C++11之左值、纯右值和将亡值

    在C 43 43 11中所有的值一定属于左值 纯右值和将亡值三种值之一 xff0c 分别介绍一下这三种类型 左值与右值 在C 43 43 中定义左值与右值的比较标准的方法是根据其可以取地址来判断 左值就是可以对变量进行取地址或者有名字的变量
  • Skip List

    Skip List 是什么 我们常用数组和链表来组织数据 xff0c 对于已排序的数据 xff0c 数组的查询时间复杂度可以是 lgn 二分查找 xff0c 插入和删除都是 n 链表提供了一种更加灵活的组织方式 xff0c 插入和删除的时间
  • 程序员的自我修养--可执行文件的装载与进程

    进程的虚拟地址空间 C语言指针大小的位数与虚拟地址空间的地址位数相同 xff0c 即32位平台下进程的虚拟地址空间为4G由于程序在运行是处于操作系统的监管下 xff0c 进程的虚拟地址空间都在操作系统的掌握中 xff0c 只能使用操作系统分
  • C++11之继承构造函数

    问题场景 类的继承中 xff0c 如果子类想使用父类的构造函数 xff0c 则需要在子类的构造函数中声明使用父类的构造函数 xff0c 例子如下 xff1a span class hljs keyword struct span A A s
  • E95-DTU(4G01-485)数传电台的特点及其应用详解

    1 E95 DTU 4G01 485简介 E95 DTU 4G01 485 是采用 4G CAT1 方案的云数传电台 xff0c 电台支持微信小程序简单配对使用 可以显现一对一 一对多 多对多等复杂应用场景 由于采用了云技术 xff0c 数
  • STM32学习笔记(串口、IAP)

    串口 xff1a 一 USART ITConfig USART1 USART IT TXE ENABLE xff1a 只要发送寄存器为空 xff0c 就会一直有中断 xff0c 因此 xff0c 要是不发送数据时 xff0c 把发送中断关闭
  • C++中容器的优点和缺点

    顺序容器 连续存储 array 优点 随机访问 一步直接得到数据的首地址的访问方式 方便 开销低 速度快 缺点 容量在定义时就确定了 不能够改变 中间删除和插入比较麻烦 需要后面的元素都移动 vector 优点 随机访问方便 可以自动扩容
  • 硬件切换485电路

    485接口具有很好的抗噪音抗干扰 长距离传输和多站能力特性 xff0c 使其为工控行业首选串行接口 485规定的电气特性为2线 xff0c 半双工多点通信 它的电气特性是有线缆两端的电压差来决定的 由于半双工模式 xff0c 通讯时需要切换
  • 802.11 Authentication and Association

    The 802 11 standard provides a method for supplying different levels of access to different nodes in a wireless local ar
  • 串口通信与波特率

    原文出自微信公众号 小小的电子之路 串口是串行接口的简称 xff0c 串行接口是采用串行通信方式的接口 串行通信是一种将需要传输的数据由低位到高位一位一位地在一条传输线上逐个传输的通信方式 一 串行通信的数据格式 首先来了解一下串行通信的数

随机推荐

  • 无人机方向控制pitch yaw roll是什么 .。欧拉角定义

    http blog csdn net yuzhongchun article details 22749521 三维空间的右手笛卡尔坐标如图1所示 图1 在航空中 xff0c pitch yaw roll如图2所示 pitch是围绕X轴旋转
  • Java学习记录

    Java学习记录 第一个Java程序tips Java对象与类变量类型构造方法创建对象源文件声明规则八大基本数据类型引用类型常量类型转换 第一个Java程序 span class token keyword public span span
  • 在Windows上搭建http服务器(lighttpd)------中秋节大礼

    今天中秋节 xff0c 也算忙了一大天了 窗外月圆 xff0c 我是不是也该吟诵 露从今夜白 xff0c 月是故乡明 这样的佳句呢 xff1f 还好 xff0c 过几天国庆就要回家了 今天继续来聊聊http服务器吧 xff01 在前面的文章
  • EPG简介

    一 EPG简介 电子节目指南 Electronic Program Guide xff0c EPG xff0c 是指在符合MPEG 2 13818 1 的TS传输流中插入DVB标准定义的业务信息 Service Information xf
  • ROS学习笔记(五)

    本文是关于第14讲的学习内容总结 所以要完成的目标是 xff0c 用C 43 43 代码编程实现服务端 Server的作用就是给海龟发布指令的 xff0c Client的作用是来控制Server是否要给海龟发布指令 老师的解释是Client
  • 433M数传电台窄带无线通讯技术手册

    一 模块介绍 1 1特点介绍 E3A DTU 500 是 一款 频率 433M 无 线数传电 台 xff08 同时 具有RS232 RS485 接口 xff09 xff0c 透明传输方式 xff0c 工作在 425 450 5MHz 频段
  • [C++]按字节读取文件

    一 背景 本文介绍了如何使用C 43 43 按字节读取 txt文件 本文第二部分为代码实例和对代码的解释 xff0c 第三部分为本文的参考文章 二 代码实例 span class token macro property span clas
  • [STL]priority_queue多种方式自定义排序

    一 背景 在做leetcode题目时很多题都需要使用优先队列 xff08 堆 xff09 xff0c 并需要使用自定义数据类型 自定义有限队列的排序方式 本文对priority queue的自定义排序方式做了总结 本文可能并不能覆盖所有自定
  • [Pyplot] 绘制三维散点图使用颜色表示数值大小

    一 摘要 在进行数据可视化时 xff0c 对于一元函数f x 61 y数据我们可以使用二维平面图显示 xff0c x轴表示自变量 xff0c y轴表示函数值 xff1b 对于二元函数f x y 61 z数据我们也可以使用三维图可视化 xff
  • [C++]<numeric>头文件介绍

    一 摘要 C 43 43 的 lt numeric gt 头文件中包含了一系列可用于操作数值序列 xff08 sequences of numeric value xff09 的函数 xff0c 通过修改函数的参数类型也可以将这些函数应用到
  • [算法] 使用位运算遍历集合的子集

    一 简介 对于使用状态压缩方法表示的集合A xff0c 如何遍历使用位运算遍历集合A的所有子集 二 代码与注释 0 符号假设 假设全集为S S的元素个数为n A为集合S的子集 可以使用状态压缩方法加位运算表示集合A 例如 xff1a S 6
  • [LaTeX|翻译]What are .cls and .sty files? How are they different?

    什么是 cls和 sty文件 xff1f 它们的区别是什么 xff1f What are cls and sty files How are they different 通常来讲 xff0c cls和 sty文件是用于增强LaTeX功能的
  • [Pyplot] 绘制3D曲面+自定义面片颜色

    一 背景 使用python 43 matplotlib实现绘制3D曲面 xff08 由多个小面片组成 xff09 xff0c 支持自定义面片颜色 xff1b 实现效果如图 a b 所示 xff1a a 使用面片法向作为面片颜色 b 使用默认
  • [STL]使用vector::erase对vector遍历删除

    在对vector中的元素进行遍历删除时遇到了一点问题 xff0c 查博客发现博客上并不靠谱 在此记录 xff0c 共同进步 vector循环遍历正确代码 span class token keyword for span span clas
  • 判断一个数是不是质数(素数),3种方式介绍

    本文参考博文判断一个数是不是质数 素数 xff0c 3种方式介绍 xff0c 原文章解释的已经很详细 xff0c 本问增加部分博主自己的理解 一 概念介绍 质数 xff1a 质数是指在大于1的自然数中 xff0c 除了1和它本身以外不再有其
  • Ubuntu/Arm安装Mysql报错:mysql-server 依赖于 mysql-server-5.7;然而:软件包 mysql-server-5.7 尚未配置。

    报错内容如下 xff1a dpkg 依赖关系问题使得 mysql server 的配置工作不能继续 xff1a mysql server 依赖于 mysql server 5 7 xff1b 然而 xff1a 软件包 mysql serve
  • E90-DTU系列无线数传电台网关与节点4gDTU通信教程

    以E90 DTU 400SL22 ETH 与E90 DTU 400SL22 为例实现网关与节点进行数据交换 xff0c 其它频段或功率的网关 节点 xff0c 其操作方式与该视频教程一致 第一步 安装网关 为网关安装天线电源模块 第二步 调
  • STM32实现将printf重定向到串口的3种方法

    STM32实现将printf重定向到串口的3种方法 目录 STM32实现将printf重定向到串口的3种方法一 使用MicroLib重定向printf二 不使用MicroLib重定向printf三 使用标准库自定义printf 函数到串口1
  • 时钟传感器—DS3231

    时钟传感器 DS3231 DS3231概述DS3231引脚DS3231寄存器DS3231 操作 DS3231概述 DS3231是一款高精度I2C实时时钟器件内部带温度补偿 闰年补偿提供两个可编程日历闹钟提供秒 分 时 星期 日期 月 年等信
  • C语言进阶

    C语言进阶 数据操作1 数据修饰 auto static register const volatile2 大端模式 小端模式 内存操作1 动态内存管理 xff08 堆区 heap xff09 malloc calloc realloc f