单片机(STM32)开发中常用的C语言基础语法(二)

9、goto语句与标签

goto语句用于无条件地转移到程序中的另一部分。它通常用于跳出循环或提前退出函数。然而,使用goto语句需要谨慎,因为过度使用它可能会导致代码难以理解和维护。

标签(Label)是一个代码标识符,后面跟一个冒号,它标识一个语句的位置。标签可以与goto语句一起使用,使程序跳转到该标签所在的语句。

#include <stdio.h>  int main() {  int i;  for (i = 0; i < 10; i++) {  printf("%d ", i);  if (i == 5) {  goto end_of_loop;  //goto语句}  }  end_of_loop:  //标签语法printf("End of loop\n");  return 0;  
}

标签可以被多次引用,这意味着可以在代码中定义相同的标签多次。但是,一个标签只能被一个语句块内的 goto 语句引用,也就是说,goto语句只能跳转到最近的被引用的标签所在的位置。这个规则是为了确保代码的可读性和可维护性。如果一个标签被多个goto语句引用,就会导致代码的流程变得不清晰,而且也不容易理解。因此,一个标签只能被一个语句块内的goto语句引用,这样可以保证代码的流程更加清晰和易于理解。

10、sscanf函数

sscanf 是一个标准C库函数,用于从字符串中读取格式化输入。它的名字代表“string scan”,意即从字符串中扫描格式化的数据。sscanf 的工作方式与 scanf 类似,但它不是从标准输入(通常是键盘)读取数据,而是从一个给定的字符串中读取。

int sscanf(const char *str, const char *format, ...);
  • str:指向要读取的字符串的指针。

  • format:一个格式字符串,指定了要读取的数据的类型和格式。

  • ...:表示可变数量的指针,这些指针指向将要存储读取数据的变量。

sscanf 函数的返回值是成功读取并赋值的输入项数,如果输入结束或发生输入失败,则可能小于提供的指针数量。

下面是一个简单的 sscanf 示例:

#include <stdio.h>  
int main() {  const char *input = "42 3.14 Hello";  int integer;  float floating;  char str[20];  // 从input字符串中读取一个整数,一个浮点数和一个字符串  int itemsRead = sscanf(input, "%d %f %19s", &integer, &floating, str);  // 打印读取到的值和读取的项数  printf("Read %d items:\n", itemsRead);  printf("Integer: %d\n", integer);  printf("Floating: %f\n", floating);  printf("String: %s\n", str);  return 0;  
}

在这个例子中,sscanf 函数尝试从 input 字符串中读取一个整数、一个浮点数和一个字符串,并将这些值存储在相应的变量中。格式字符串 "%d %f %19s" 指定了要读取的数据类型和格式:一个整数(%d)、一个浮点数(%f)和一个最多包含19个字符的字符串(%19s)。注意,字符串的读取长度被限制为19个字符,以避免缓冲区溢出。

11、左移右移操作符<< >>

  1. 左移运算符 (<<)

    • 将左操作数的所有位向左移动指定的位数,右侧空出的位用0填充。

    • 有一个8位的二进制数 00001010 (十进制中的10)。如果我们将其左移1位,结果为 00010100 (十进制中的20)。

    • 左移操作相当于乘以2的某个幂。例如,左移1位相当于乘以2,左移2位相当于乘以4,以此类推。

  2. 右移运算符 (>>)

    • 将左操作数的所有位向右移动指定的位数。

    • 对于无符号整数,右侧溢出的位被丢弃,左侧空出的位用0填充。

    • 对于有符号整数,右移的处理方式依赖于具体的编译器或机器。在许多环境中,算术右移会保留符号位(即最左边的位),这意味着负数的右移会在左侧填充1,而正数或0的右移会在左侧填充0。但在某些环境中,也可能采用逻辑右移,即无论符号如何,都在左侧填充0。

    • 有一个8位的二进制数 00001010 (十进制中的10)。如果我们将其右移1位,结果为 00000101 (十进制中的5)。

    • 右移操作可以被视为整除2的某个幂。例如,右移1位相当于除以2,右移2位相当于除以4(忽略余数),以此类推。

12、strcmp函数

strcmp 函数是 C 语言标准库中 <string.h> 头文件提供的一个函数,用于比较两个字符串,其语法如下:

int strcmp(const char *str1, const char *str2);
  • str1:要比较的第一个字符串。指向第一个要比较的 null 结尾字符串的指针

  • str2:要比较的第二个字符串。指向第二个要比较的 null 结尾字符串的指针

strcmp函数会比较两个字符串str1str2,如果两个字符串相等,则返回0;

如果str1小于str2,则返回一个负数;

如果str1大于str2,则返回一个正数。

以下是一个简单的示例代码,演示如何使用strcmp函数:

#include <stdio.h>
#include <string.h>int main() {char str1[] = "hello";char str2[] = "world";int result = strcmp(str1, str2);if (result == 0) {printf("两个字符串相等\n");}else if (result < 0) {printf("第一个字符串小于第二个字符串\n");}else {printf("第一个字符串大于第二个字符串\n");}return 0;
}

在上面的示例代码中,我们比较了两个字符串str1str2,并根据strcmp函数的返回值输出不同的结果。

13、strlen/sizeof函数

在C语言中,strlensizeof 是两个不同的操作,它们用于不同的目的。

  1. strlen 函数用于计算字符串的长度,不包括 null 终止字符 '\0'。strlen 是 C 标准库中 <string.h> 头文件提供的函数。下面是它的语法:

#include <string.h>
size_t strlen(const char *str);

函数参数:

  • str: 指向以 null 结尾的字符串的指针。

返回值:

  • 返回 str 所指向的字符串的长度,不包括 null 终止字符。

用法示例:

#include <stdio.h>
#include <string.h>
int main() {const char *str = "Hello, World!";size_t length = strlen(str);printf("Length of the string is: %zu\n", length);return 0;
}

这段代码会输出字符串 "Hello, World!" 的长度,不包括结尾的 null 字符。

  1. sizeof 操作符用于计算变量或类型所占的字节数。它在编译时计算,而不是运行时。下面是它的用法:

size_t size = sizeof(object_or_type);

用法示例:

#include <stdio.h>
int main() {int arr[10];size_t sizeInBytes = sizeof(arr);printf("Size of the array is: %zu bytes\n", sizeInBytes);return 0;
}
//%zu 是一个格式说明符,用于 printf 或 scanf 等格式化输入输出函数中。它用来匹配 size_t 类型的数据。使用 %zu 格式说明符可以确保无论 size_t 是多大,都能正确地打印其值,而不会发生整型溢出或类型不匹配的问题。

这段代码会输出整型数组 arr 的大小(以字节为单位),因为 arr 包含 10 个整数,所以如果一个整数占 4 个字节,那么输出将会是 40 字节。

  • strlen 返回的是字符串的实际长度,直到遇到第一个 null 字符。

  • sizeof 返回的是数组分配的总字节数,对于字符串,这包括末尾的 null 字符。如果 sizeof 用于指针,它将返回指针本身的大小,而不是指针所指向的数据的大小。

14、memset函数

memset(rx_data, 0, sizeof(rx_data));memset常用于清空串口接收缓存,rx_data是自己定义用来存放串口数据的变量

在C语言中,memset函数的语法如下:

void *memset(void *ptr, int value, size_t num);
  • ptr:指向要设置数值的内存起始地址的指针。

  • value:要设置的值,通常是一个无符号字符(unsigned char),但传入int类型也可以,会被截断为无符号字符。

  • num:要设置的字节数,即连续内存块的大小。

memset函数通常用于将一块内存区域的值设置为指定的值,可以是0、-1或其他特定值。例如,将一个数组的所有元素初始化为0,可以使用memset函数:

int arr[10];
memset(arr, 0, sizeof(arr));
char rx[20];
memset(rx,0,strlen(rx));

这样就会把数组arr中的所有元素设置为0。

15、strtok函数

strtok 函数是 C 语言标准库中的一个用于分割字符串的函数。它可以用来将字符串分割成一系列的标记(token),分割是根据一组指定的分隔符来完成的。

函数原型如下:

#include <string.h>
char *strtok(char *str, const char *delim);

参数:

  • str: 要分割的原始字符串。第一次调用 strtok 时,str 应该指向要分割的字符串。此后,要继续分割同一个字符串,就应该传递 NULL 作为 str 参数,这样函数就会继续处理上次调用时剩下的部分。

  • delim: 包含所有分隔符的字符串。这些字符中的任何一个都可以作为标记的分隔符。

返回值:

  • 返回指向当前标记的指针,如果没有剩余的标记,则返回 NULL

注意: strtok 函数使用一个静态缓冲区来存储当前的位置,所以它不是线程安全的。在多线程环境中应当使用 strtok_r,这是它的线程安全版本。

strtok 的工作方式是,它在 str 指向的字符串中查找 delim 中的字符。当它找到一个这样的字符时,它会用 \0(空字符)替换掉,并返回指向当前标记起始位置的指针。在连续调用中,它会继续从上次停下来的地方开始查找下一个标记。

示例代码:

#include <stdio.h>
#include <string.h>
int main() {char str[] = "This is a sample string";char *token;//strtok的返回值是一个指针char *rest = str;// 获取第一个标记token = strtok(rest, " ");while (token != NULL) {printf("%s\n", token);// 为了获取后续的标记,rest 应该被设置为 NULLtoken = strtok(NULL, " ");}return 0;
}

在上面的例子中,strtok 被用来分割字符串 str,每当遇到空格 " " 时,就会分割出一个新的标记。每个标记在控制台上单独一行打印出来。第一次调用 strtok 时,rest 指向要分割的字符串;之后,为了继续分割同一个字符串,我们传递 NULLstrtok

strtok 函数找到一个标记时,它会在标记的末尾添加一个 \0(空字符)来终止这个标记。然后,strtok 返回一个指向这个标记起始位置的指针。这意味着,它返回的是一个指向原始字符串 str 内部的一个位置的指针,而不是创建一个新的字符串。

这里的“当前标记”是指 strtok 根据提供的分隔符 delimstr 或其后续调用中剩余部分中找到的第一个标记。标记是指原字符串中由分隔符分隔的子字符串

具体来说,假设你有以下字符串和调用:

char str[] = "hello,world,this,is,a,test";
char *token = strtok(str, ",");

在第一次调用 strtok 后,原始字符串 str 在内存中的表示会被修改。strtok 会在第一个分隔符(,)的位置放置一个 \0 字符,因此原始字符串 str 现在看起来像两个字符串:"hello" 和 "world,this,is,a,test"。

strtok 的返回值是指向原始字符串中第一个标记(在这个例子中是单词 "hello")的第一个字符的指针。因此,第一次调用 strtok 后,token 指向的是 "hello"。

继续调用 strtok(NULL, ",") 会继续从上次停止的位置开始查找下一个标记,并重复相同的过程(在下一个分隔符处放置 \0,并返回指向当前标记的指针)。这意味着,随着 strtok 的每次调用,原始字符串 str 会被进一步分割,strtok 返回的指针将指向这些新形成的标记。

这种方法的一个后果是 strtok 修改了原始字符串,所以如果你需要保留原始字符串未被修改的状态,你应该先对它进行复制。

16、size_t

size_t 是 C 和 C++ 编程语言中定义的一种数据类型。它是一个无符号整数类型,通常用于表示大小(如数组长度、字符串长度等)和基于内存的计算(如内存分配大小)。size_t 类型足够大,能够表示任何对象的大小,包括数组和字符串的最大可能大小。

这个数据类型在 <stddef.h>(在 C 语言中)和 <cstddef>(在 C++ 中)头文件中定义。由于它是无符号的,size_t 类型的值永远不会是负数。

size_t 的确切大小依赖于平台和编译器,但它必须至少能够表示编译器支持的最大对象大小。在许多 32 位系统上,size_t 是 32 位无符号整数;在 64 位系统上,它通常是 64 位无符号整数。

使用 size_t 而不是 int 或其他整数类型进行内存相关的计算和表示,有助于提高代码的可移植性和安全性,因为它能够适应不同平台上的地址空间大小变化。

下面是一些使用 size_t 的例子:

例子 1:使用 size_t 作为数组索引和循环计数器

#include <stdio.h>
int main() {int numbers[] = {1, 2, 3, 4, 5};size_t numbers_count = sizeof(numbers) / sizeof(numbers[0]);
// 使用 sizeof 运算符计算数组总大小,然后除以单个元素的大小,得到数组元素的数量for (size_t i = 0; i < numbers_count; ++i) {
// 使用 size_t 类型的 i 作为循环计数器,从 0 遍历到数组的长度(不包括这个长度)printf("%d ", numbers[i]);}return 0;
}

例子 2:使用 size_t 接收 strlen 函数的返回值

#include <stdio.h>
#include <string.h>
int main() {char myString[] = "Hello, World!";size_t strLength = strlen(myString);printf("The length of '%s' is %zu.\n", myString, strLength);
//%zu 是一个格式说明符,用于 printf 或 scanf 等格式化输入输出函数中。它用来匹配 size_t 类型的数据。return 0;
}

在这些例子中,使用 size_t 来处理与大小相关的值,可以确保代码在不同的系统和编译器配置中具有良好的兼容性和正确性。

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

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

相关文章

柯西变异和正余弦改进的麻雀搜索算法及python实现

目录 柯西变异和正余弦改进的麻雀搜索算法第一部分:麻雀搜索算法概述1.1 麻雀搜索算法简介1.2 算法特点1.3 算法流程1. 初始化阶段2. 觅食者搜索阶段3. 监视者逃逸阶段4. 判断收敛条件1.4 公式描述第二部分:改进方法——柯西变异与正余弦机制2.1 改进思路2.2 柯西变异公式2.3…

Scala文件读写——成绩分析

根据文件解决下例问题 1.读入txt文件&#xff1a;按行读入 import scala.io.Sourceobject Test文件读写_成绩分析 {def main(args: Array[String]): Unit {//1.按行读入val source Source.fromFile("score.txt")val it source.getLines()it.next()//跳过第一行wh…

C# Winform 俄罗斯方块小游戏源码

文章目录 1.设计来源俄罗斯方块小游戏讲解1.1 主界面1.2 游戏界面1.3 游戏结束界面1.4 配置游戏界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https:…

前端框架Vue3——响应式数据,v-on,v-show和v-if,v-for,v-bind

Vue的定义为渐进式的JavaScript框架。所谓渐进式&#xff0c;是指其被设计 为可以自底向上逐层应用。我们可以只使用Vue框架中提供的某层的功 能&#xff0c;也可以与其他第三方库整合使用。当然&#xff0c;Vue本身也提供了完整的 工具链&#xff0c;使用其全套功能进行项目的…

实验二 系统响应及系统稳定性

实验目的 &#xff08;1&#xff09;学会运用Matlab 求解离散时间系统的零状态响应&#xff1b; &#xff08;2&#xff09;学会运用Matlab 求解离散时间系统的单位取样响应&#xff1b; &#xff08;3&#xff09;学会运用Matlab 求解离散时间系统的卷积和。 实验原理及实…

.NET Core发布网站报错 HTTP Error 500.31

报错如图&#xff1a; 解决办法&#xff1a; 打开任务管理器》》服务》》找到这仨服务&#xff0c;右键启动即可&#xff0c;如果已经启动了就重启&#xff1a;

FFmpegFrameRecorder 切分视频文件时结束条件设置不当导致切分后的文件过短问题

问题 下游反馈使用 ffmpeg 切割后的音频文件&#xff0c;无法正确识别其声音的性别 排查流程 1&#xff0c;由于线上大部分用户上传音频后&#xff0c;进行切分后的音频都没问题&#xff0c;因此考虑到这些无法识别性别的音频&#xff0c;有格式问题&#xff0c;需要找出其共…

真题-桂城2018年六年级

01.整点 题目描述 在二维坐标系, 有一个圆&#xff0c;圆心在(0,0)&#xff0c;圆的半径是r。问圆内有多少个整点(所谓的整点就是横坐标和纵坐标都是整数的点)。 若点P的横坐标是整数a&#xff0c;纵坐标是整数b&#xff0c;那么只要满足aa bb < r*r, 那么P就是圆内的整点…

【快捷入门笔记】mySQL基本操作大全-运算符和句子

一、ORDER BY 排序 排序方式 1.升序&#xff1a;ASC&#xff08;默认就是升序&#xff09; 2.降序&#xff1a;DESC 3.如果有多个排序条件&#xff0c;前面的值一样时才会判断第二条件 --按照数学成绩排序 select*from Student ORDER BY math --按照数学成绩排序&#xff0c;…

麒麟安全增强-kysec

DAC: 自主访问控制是linux下默认的接入控制机制,通过对资源读、写、执行操作,保证系统安全 MAC:安全接入控制机制,由操作系统约束的访问控制,默认情况下,MAC不允许任何访问,用户可以自定义策略规则制定允许什么 ,从而避免很多攻击。 MAC强制访问控制常见的实现方式:…

java多线程——synchronized的偏向锁、轻量级锁和重量级锁

在Java中&#xff0c;synchronized关键字是用于实现线程同步的一种机制&#xff0c;它提供了偏向锁、轻量级锁和重量级锁三种锁状态来优化同步性能。以下是这三种锁的原理和使用方法的详细解释&#xff1a; 一、偏向锁&#xff08;Biased Locking&#xff09; 原理 偏向锁的目…

Otter 安装流程

优质博文&#xff1a;IT-BLOG-CN 一、背景 随着公司的发展&#xff0c;订单库的数据目前已达到千万级别&#xff0c;需要进行分表分库&#xff0c;就需要对数据进行迁移&#xff0c;我们使用了otter&#xff0c;这里简单整理下&#xff0c;otter 的安装过程&#xff0c;希望对…

速盾:ddos防御手段哪种比较好?高防cdn怎么样?

DDoS&#xff08;分布式拒绝服务&#xff09;攻击是一种威胁网络安全的常见攻击手段。为了保护网站和服务器免受DDoS攻击的影响&#xff0c;许多安全专家和公司开发了各种防御手段。在这篇文章中&#xff0c;我们将重点讨论一种常见的DDoS防御手段——高防CDN&#xff08;内容分…

faiss VS ChromaDB

faiss faiss 是一个开源的机器学习库&#xff0c;由Facebook AI Research&#xff08;FAIR&#xff09;开发&#xff0c;主要用于高效的大规模向量搜索和聚类。 faiss 的核心优势在于它为高维向量空间中的数据提供了快速的近似最近邻搜索&#xff08;ANNS&#xff09;算法&am…

微信小程序导航方式详解:声明式导航与编程式导航

微信小程序导航方式详解:声明式导航与编程式导航 引言 在微信小程序的开发中,页面导航是实现用户交互的重要组成部分。小程序提供了两种主要的导航方式:声明式导航和编程式导航。了解这两种导航方式的特点、使用场景及其优缺点,对于提升小程序的用户体验和开发效率至关重…

如何解决Jupyter command `jupyter-contrib` not found.

目录 (base) C:\Users\hello>pip show jupyter_contrib_nbextensions Name: jupyter-contrib-nbextensions Version: 0.7.0 Summary: A collection of Jupyter nbextensions. Home-page: https://github.com/ipython-contrib/jupyter_contrib_nbextensions.git Author: ipyt…

Gitee markdown 使用方法(持续更新)

IPKISS 获取仿真器件的名称 引言正文标题换行第一种------在行末尾手动键入两个空格第二种------额外换行一次&#xff0c;即两行中间留一个空行 缩进与反缩进代码块行内代码添加图片添加超链接 加粗&#xff0c;倾斜&#xff0c;加粗倾斜 引言 有些保密性的文件或者教程&…

Adobe Illustrator 2024 安装教程与下载分享

介绍一下 下载直接看文章末尾 Adobe Illustrator 是一款由Adobe Systems开发的矢量图形编辑软件。它广泛应用于创建和编辑矢量图形、插图、徽标、图标、排版和广告等领域。以下是Adobe Illustrator的一些主要特点和功能&#xff1a; 矢量绘图&#xff1a;Illustrator使用矢量…

golang学习5

为结构体添加方法 异常处理过程

分布式光伏与储能协调控制策略的应用分析

安科瑞汪洋/汪小姐/汪女士---Acrelwy 摘 要&#xff1a;针对光伏发电的随机性、波动性、间歇性特征,研发了分布式光伏与储能协调控制策略,并在镇江地调开展分布式电源光储协控试点应用&#xff0c;开展光储协调控制策略研究&#xff0c;实时采集分布式光伏电站、储能电站、试点…