learn_C_deep_8 (循环语法的理解、void的用法以及理解)

news2024/12/24 10:01:28

目录

循环语法的理解

break关键字

continue关键字 

 continue跳转的位置

goto关键字

void的用法以及理解

void是否可以定义变量

为何 void 不能定义变量

void的应用场景

void 指针


循环语法的理解

        for循环是一种常用的循环结构,它适合于在已知循环次数的情况下重复执行相同的代码块。for循环语法如下:

for(条件初始化; 条件判定; 条件更新){
        //业务代码
}

        while循环是另一种常用的循环结构,它适合于在不知道循环次数的情况下重复执行代码块,只需要在每次循环前先检查一次循环条件。 while循环语法如下:

条件初始化
while(条件判定){
        //业务更新
条件更新
}

        do-while循环和while循环很类似,它们的区别在于do-while循环的判断是在循环体执行完后才进行的,因此它保证了循环体至少能够被执行一次。 do-while循环语法如下:

条件初始化
do{
        条件更新
}while(条件判定);

三种循环对应的死循环写法场景

while(1)

{

        while语句

}

for(;;)

{

        for语句;

}

do

{

        do-while语句;

}while(1);

        在C语言中,每个程序都有三个默认打开的流,即标准输入流(stdin)、标准输出流(stdout)和标准错误流(stderr)。它们分别对应键盘输入、屏幕输出和错误信息输出,可以在程序中使用它们来读取或写入数据,或者输出一些提示信息、错误信息等。在C语言中,我们可以使用各种标准输入输出函数(如printf、scanf、fgets等)来访问这些默认的流,从而实现程序的输入输出。同时,这三个标准流也可以在程序中进行重定向,例如将标准输出流重定向到文件上,从而将程序的输出内容保存到文件中。

        在图片的代码中,为什么我们的代码没有文件操作,却会打开这些流呢?

        实际上,你使用标准输入输出函数时,代码中并没有显式的文件操作代码,因为标准库已经将文件操作封装到标准输入输出函数中了。标准输入输出函数是使用FILE数据类型来操作标准输入输出流的。标准输入、输出、错误输出描述符在程序开始执行时就已经被打开了,因此当你使用标准输入输出函数时,实际上是操作这些默认打开的流,而不需要显式地打开文件。

例如,当你使用printf函数将输出内容写入标准输出流(通常是控制台屏幕)时,实际上是写入到了stdout指向的流。同样,当你使用scanf函数从标准输入流(通常是键盘输入)读取输入内容时,实际上是从stdin指向的流读取数据。  

了解上面的内容后,我们再来了解一下getchar函数。

        getchar函数是一个标准输入函数,用于从标准输入流(stdin)中读取一个字符。

它的函数原型如下:

        getchar函数不需要任何参数,当从标准输入流中读取到一个字符时,它会将该字符作为返回值返回给调用者。如果从流中读取到文件结束标志EOF(End-Of-File),则返回EOF。        

        因此,我们可以根据getchar函数的返回值来判断是否读取到有效字符。 在使用getchar函数时,需要注意以下几点:

1. 当程序使用getchar函数时,它会一次读取一个字符,如果想要读取多个字符,需要使用循环语句(如while、for等)结合getchar函数来实现。

2. 在读取字符时,getchar函数会自动忽略空白字符(如空格、制表符、回车等),直到读取到一个非空白字符为止。如果想要读取空白字符,可以使用scanf函数等其他读取函数。

我们接下里就来看看循环语法和getchar函数的应用

#include <stdio.h>
#include <windows.h>
int main()
{
	while (1) { //while的死循环写法
		char c = getchar(); 
		if ('#' == c) {
			break;//结束死循环
		}
		printf("%c\n", c);
	}
	system("pause");
	return 0;
}

getchar的返回值类型为什么是int,而不是char。

        实际上,C语言规定getchar函数的返回值类型为int,而不是char。这是为了能够表示EOF(End-Of-File)值,其值宏定义为-1。

        在标准输入流中,如果读取到文件结束标志EOF,getchar函数会返回EOF,以便程序能够正确地判断文件是否已经读取完毕。如果将getchar函数的返回值类型定义为char,那么EOF就无法被正确地表示,因为EOF是一个int类型的常量。例如,如果getchar函数的返回值类型是char,那么当从标准输入流中读取到EOF时,getchar函数会返回char类型的-1。此时,程序就无法正确地判断是读取到了EOF,还是实际上读取到了字符-1。

       此外,在一些特殊情况下,比如运行在宽字符环境下时,一个字符可能需要占用多个字节,此时将返回值类型设置为 int,可以避免数据截断。例如:当我们读取到1 0000 0000,而读取char类型只有八个比特位,此时读取的就是0000 0000在其合法范围内,那么就会读取错误的数据。

        因此,C语言规定getchar函数的返回值类型为int,以便在读取到EOF时能够正确地返回EOF值,让程序能够正确地判断文件是否已经读取完毕。

总结:使用getchar一定不能忘记你自身输入的回车符(`\n`)。 

break关键字

        `break` 关键字是C语言中用于控制循环语句的关键字,它用于立即退出当前循环,并跳到循环语句后面的代码中执行。

continue关键字 

        `continue` 关键字是C语言中用于控制循环语句的关键字,它可以用于跳过当前循环中剩余的语句,直接进入下一次循环。

 continue跳转的位置

总结:while语句和do-while语句判断条件在的位置就是continue跳转的位置,而for语句的条件更新在的位置就是continue跳转的位置。

goto关键字

        `goto`关键字是一种跳转语句,它可以用于无条件地跳转到程序中的某个标记(label)处继续执行,但仅仅是本代码块内,不可跨函数、文件使用。

#include <stdio.h>
#include <windows.h>
int main()
{
	int i = 0;
START:
	printf("[%d]goto running ... \n", i);
	Sleep(1000);
	++i;
	if (i < 10) {
		goto START;
	}
	printf("goto end ... \n");
	system("pause");
	return 0;
}

        这是一段 C 语言的程序代码。它使用了 goto 语句来实现循环的功能。程序开始时,定义了一个计数器变量 i,并初始化为 0。然后使用标签 START,打印输出一条信息,暂停程序执行一秒钟,计数器变量自加 1。接着判断计数器变量 i 是否小于 10,如果小于 10,则跳转到标签 START 处重新执行循环;否则,打印输出一条结束信息,暂停程序执行并等待用户按下任意键结束程序。总的来说,这段程序使用了 goto 语句来实现了一个简单的循环结构,但是因为 goto 容易导致程序流程混乱,使用时要谨慎。

void的用法以及理解

        在C语言中,void是一种特殊的数据类型,表示“无类型”或“空类型”。

void是否可以定义变量

        在C语言中,void是一种“空类型”,它没有具体的值或大小,因此不能定义为变量类型,也不能用作变量的数据类型。

  很明显,在vs编译器中是错误的,禁止运行。我们再用sizeof求一下它所占的空间。

很明显,空间大小为0,自然也就不能开辟空间。

总结:void本身就被编译器解释为空类型,强制的不允许定义变量

为何 void 不能定义变量

        定义变量的本质:开辟空间

        而void作为空类型,理论上是不应该开辟空间的,即使开了空间,也仅仅作为一个占位符看待。所以,既然无法开辟空间,那么也就无法作为正常变量使用,既然无法使用,编译器干脆不让他定义变量。

在vs2013中,sizeof(void)=0

在Linux中,sizeof(void)=1(但编译器依旧理解成,无法定义变量)

void的应用场景

        1.用于函数的返回值类型。在C语言中,函数可以返回各种不同类型的数据,但是有些函数并不需要返回任何值,这时候就可以使用void类型的函数。void函数不需要使用return语句,因为它们不返回任何值。

 但是自定义函数,没有返回值,如果不写void,会让阅读你代码的人产生误解:他是忘了写,还是想默认int?这样就会导致代码的体验感变差。

 总结:void作为函数返回值,代表不需要,这里是一个"占位符"的概念,是告知编译器和给阅读源代码看的,建议程序如果没有返回值的时候,将返回值类型写成void。

        2.用于函数参数类型。当一个函数不需要接受任何参数时,可以使用void作为函数参数类型。例如,int main(void) 是一个不接受任何参数的函数。

         总结:如果一个函数没有参数,将参数列表设置成void,是一个不错的习惯,因为可以将错误明确提前发现,另外,阅读你代码的人,也一眼看出,不需要参数。相当于"自解释"。

        3.用于指针类型。在C语言中,void*指针可以指向任何类型的数据,但是它不能被直接解引用,必须先进行类型转换才能使用。因此,void指针常用于作为通用指针类型,用于传递指针参数,例如: ```c void print(void *data, size_t size);

void 指针

void不能定义变量,那么void*呢?

#include <stdio.h>
#include <windows.h>
int main()
{
	void* p = NULL; //可以
	system("pause");
	return 0;
}

 void*定义变量no error!

为什么void*可以呢?

因为void*是指针,是指针,空间大小就能明确出来,有空间就可以创建变量。

void* 能够接受任意指针类型

#include <stdio.h>
int main()
{
	void* p = NULL;
	int* x = NULL;
	double* y = NULL;
	p = x; //虽然类型不同,但是编译器并不报错 x - int*
	p = y; //同上 y - double*
	return 0;
}

        `void*` 可以接受任意指针类型是因为C语言中所有指针类型的大小都是相同的。指针的大小和所指向的数据类型没有关系,它只与寻址空间的大小有关,通常为4个字节或8个字节。因此,任意类型的指针都可以转换成 `void*` 类型指针,因为这种转换不会改变指针所占用的大小和指向的内存空间。

当我们反过来将void*赋给x,y呢?

#include <stdio.h>
int main()
{
	void* p = NULL;
	int* x = NULL;
	double* y = NULL;
	p = x; //虽然类型不同,但是编译器并不报错 x - int*
	p = y; //同上 y - double*

	x = p;
	y = p;
	return 0;
}

同样没有报错,甚至连警告都没有。

总结:void*可以被任何类型的指针接收,同时也可以接收任意指针类型(常用)。

void * 定义的指针变量可以进行运算操作吗?

#include <stdio.h>
int main()
{
	void* p = NULL;
	p++; //报错
	p += 1; //报错
	return 0;
}

        `void*` 指针类型是一个通用的指针类型,用于通用的指针操作,它本身是一个无类型指针,不直接支持指针运算。

        由于 `void*` 指针类型无法知道它指向的内存的数据类型和占用多少字节,所以在使用 `void*` 类型指针时,不能进行指针运算。若对 `void*` 类型指针进行加、减、乘、除、位运算等操作是没有意义的,并且这样的操作通常会导致编译错误。

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

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

相关文章

ChatGPT prompt engineering (中文版)笔记 |吴恩达ChatGPT 提示工程

目录 一、资料二、 指南环境配置两个基本原则&#xff08;最重要!!!!&#xff09;原则一&#xff1a;编写清晰、具体的指令**策略一&#xff1a;使用分隔符清晰地表示输入的不同部分**&#xff0c;**分隔符可以是&#xff1a;&#xff0c;""&#xff0c;<>&…

浅谈几个通信概念-如何理解卷积,负频率,傅里叶变换,奈奎斯特采样定理?

1.如何理解卷积&#xff1f; t时刻的输出信号是t时刻之前的无数小的脉冲序列冲击引起的。 2. 如何理解欧拉公式&#xff0c;复指数信号呢&#xff1f; 可以看成一个点在复平面上以角速度w进行逆时针的旋转。 傅里叶分析&#xff1a; 整体到部分&#xff0c;把一个信号分解成无…

【网络】socket套接字基础知识

文章目录 IP与端口号TCP/UDP协议网络字节流socket套接字接口总结 IP与端口号 IP 每台主机都有自己的IP地址&#xff0c;所以当数据从一台主机传输到另一台主机就需要IP地址。报头中就会包含源IP和目的IP 源IP地址&#xff1a;发送数据报那个主机的IP地址&#xff0c;目的IP地…

JMeter开发web及手机APP自动化脚本练习

一、打开浏览器代理服务器设置 我这里用的是360浏览器&#xff0c;打开浏览器代理服务器设置&#xff0c;端口要与jmeter中的端口设置保持一致哦。 二、JMeter设置代理 JMeter设置代理&#xff08;jmeter中的端口要与360浏览器端口设置保持一致哦。&#xff09; 三、启动代理运…

BM17 二分查找-I

二分查找-I_牛客题霸_牛客网 (nowcoder.com) 设置中间值mid 每次判断目标值和中间值的大小 缩短区间 直到区间全被搜索完成 class Solution { public: /** * 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可 * * * param nums …

因子挖掘框架cs优缺点介绍和使用说明

cs框架的优点和缺点 优点和ts一样,就是速度非常快缺点有好几个:必须使用根据过去一定天数计算因子值,持有一定天数之后再平衡的模式;必须使用连续的数据,如果是期货期权等需要合成连续数据。资金不足的时候不会拒单。cs框架使用方法 设计理念 计算因子由用户进行计算,因…

Yolov7论文详解

论文地址&#xff1a;https://arxiv.org/pdf/2207.02696.pdfhttps://arxiv.org/pdf/2207.02696.pdf 项目地址&#xff1a; WongKinYiu/yolov7: Implementation of paper - YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors (gith…

多进程多线程并发服务器代码实现

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

R语言:鉴于计算10亿以内训练模型记录for循环的加速

文章目录 1 前言2 几个循环2.1 100以内的和2.2 100以内奇数和/偶数和 3 多重循环3.1 向量化3.2 合并循环3.3 apply函数3.4 矩阵运算3.5 foreach分解任务 4 讨论 1 前言 笔者主力机是MBAM1芯片&#xff08;8256&#xff09;&#xff0c;某个下午巩固循环突然思考到个问题&#…

【Luenberger Observer】龙贝格观测器及示例Matlab仿真

目录 龙贝格观测器 龙贝格观测器示例和仿真 Matlab仿真 龙贝格观测器 观测器&#xff1a;根据系统的输入u和输出y估计系统的状态x。 SISO系统的状态空间方程如下 龙贝格观测器&#xff0c;通过在原系统添加基于输出误差校正项&#xff0c;构造状态空间方程&#xff0c;设x_h…

如何用Jmeter压测Netty的Echo服务之自定义Jmeter的Java Sampler

前言 如果想要压测一些三方组件&#xff0c;比如MQ&#xff0c;redis什么的&#xff0c;jmeter本身是不支持的。 本文以开发一个压测netty的echo示例&#xff0c;说明如何自定义jmeter的sampler。 开发 本文以idea示例&#xff0c; 新建工程 打开idea新建一个空的maven工程…

yolov8 ONNX Runtime C++ 部署

其实个人偏爱用OpenCV DNN 部署&#xff0c;但是在前面一篇博客发现还要升级OpenCV。 笔记本的CPU 是AMD 牌子的&#xff0c;就只能用 ONNX Runtime 部署了。 目录 Pre: cv::dnn::blobFromImages() gettimeofday() rand() template 代码 utils.h utils.cpp detect.h…

uboot第一阶段 start.S代码分析

u-boot.lds中找到start.S入口 (1)C语言规定整个项目的入口就是main函数。 (2)在uboot中因为有汇编阶段参与&#xff0c;因此不能直接找main.c。整个程序的入口取决于链接脚本中ENTRY声明的地方。ENTRY(_start)因此定义_start符号 的文件就是整个程序的起始文件&#xff0c;即st…

python报错提示以及logger的一些应用

本篇是拆解这篇【python︱函数、for、if、name、迭代器、防范报错、类定义、装饰器、argparse模块、yield 】 将报错 logger提示拿出来 文章目录 1、防范报错1.1 assert 断言 2 try...except...报错并提示异常信息优雅的异常报错&#xff1a;suppress 3、报错日志记录&#xf…

【Java 并发编程】一文详解 Java 内置锁 synchronized

一文详解 Java 内置锁 synchronized 1. 前言1.1 并发编程中存在线程安全问题1.2 设计同步器的意义1.3 如何解决线程并发安全问题&#xff1f; 2. synchronized 的用法2.1 修饰实例方法&#xff0c;锁是当前实例对象2.2 修饰静态方法&#xff0c;锁是当前类对象2.3 修饰代码块&a…

简单创建SSM项目

1、在idea中创建项目 点击new-project&#xff0c;点击Maven项目&#xff0c;勾选 creat from archetype &#xff0c;找到maven-archetype-webapp 写好相关信息 点击下一步&#xff0c;需要检查maven环境 点击后下载对应的插件&#xff0c;选择项目地址。 开始下载资源&#x…

rust vscode编辑器常用插件与配置

插件&#xff1a;rust-analyzer 会实时编译和分析你的 Rust 代码&#xff0c;提示代码中的错误&#xff0c;并对类型进行标注 插件的完整手册地址&#xff1a;https://rust-analyzer.github.io/manual.html。 插件&#xff1a; rust syntax 为代码提供语法高亮。 …

就挺无语的,这是有脾气的博客

文章目录 前言1. 背景2. 使用3. 公众号体验4. 结束语 前言 ChatGPT已经推出两个多月了&#xff0c;热度已经不减。ChatGPT由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型&#xff0c;一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的…

大厂都用DevOps!十分钟带你了解自动化在DevOps中的运用

Hi&#xff0c;大家好。DevOps、CI/CD、Docker、Kubernetes……好像全世界都在谈论这些技术&#xff0c;以至于你觉得即将到达NoOps阶段。别担心&#xff0c;在工具和各种最佳实践的浩瀚海洋中感到迷失是正常的&#xff0c;是时候让我们来分析一下DevOps到底是什么了。 一、De…

JAVA类加载机制

在Java的世界里&#xff0c;每一个类或者接口&#xff0c;在经历编译器后&#xff0c;都会生成一个个.class文件。 类加载机制指的是将这些.class文件中的二进制数据读入到内存中&#xff0c;并对数据进行校验&#xff0c;解析和初始化。最终&#xff0c;每一个类都会在方法区保…