C语言 —— 初步入门知识(选择与循环语句、函数、数组、操作符、关键字和#define)

本篇文章将接着上篇继续介绍C语言的基础知识,使读者对C语言能够有一个大概的认识. 不会细写每一个知识点, 但是能够入门C语言, 进行初步的C语言代码阅读.

1. 选择语句

假设你要决定是否出门玩耍,如果天气晴朗,你就出门;如果天气不好,你就呆在家里。这是我们生活中的例子.

当编写程序时,经常需要根据不同情况执行不同的操作。C语言中的选择语句允许我们根据条件来选择执行哪些代码。

int main() 
{int isSunny = 0; // 假设1表示晴朗,0表示不晴朗printf("天气好吗(1/0)?");scanf("%d\n", &isSunny);if (isSunny) {printf("今天天气晴朗,出门玩耍!\n");}else{printf("今天天气不好,呆在家里吧。\n");}return 0;
}
当然, C语言中还有switch语句用于实现选择.

2. 循环语句

循环语句在编程中用于重复执行一段代码,直到满足某个条件为止。我们在这里介绍while循环.

int main()
{int line = 0;printf("好好学习\n");while (line < 20000){printf("写代码: %d\n", line);line++;}if (line >= 20000){printf("好offer");}else{printf("继续加油\n");}return 0;
}

可以看到, 在运行窗口中打印了两万次的写代码计数.

3. 函数

我们来看下面的代码:

程序执行后在控制台输入10 20, 按下回车就可以进行求和的一个计算.

在求和部分的代码我们是使用了一个表达式来计算结果, 那么我们可以使用一个函数来进行这个计算的工作.

类似于之前strlen()求字符串长度的函数, 该函数完成了求长度的工作, 然后把结果返回并给到len, 最后打印.
也类似于数学中的函数, 比如函数, 通过给入不同的x值, 可以得出不同的函数值.
// 定义一个返回类型为int, 名为的函数, 在主函数中让 n1 传给 函数参数x, n2 传给 函数参数y.
int Add(int x, int y)
{int z = 0;z = x + y;return z; 
}int main()
{int n1 = 0;int n2 = 0;// 输入scanf("%d %d", &n1, &n2);// 求和//int sum = n1 + n2;int sum = Add(n1, n2);// 打印printf("%d\n", sum);return 0;
}

我们可以将函数想象成一个工厂, 工厂的原理是利用原材料进行加工, 生产得到产品.
函数也是一样, 它就相当于是工厂的角色, n1和n2就相当于是原材料, z就是相当于产品的结果.
那么n1, n2就是 输入数据, z就是 输出数据.
在函数Add{}中的代码就称为 函数体.

注: 也可以直接在返回语句中进行计算.

int Add(int x, int y)
{return x + y;
}

4. 数组

要存储1-10的数字,怎么存储?

C语言中给了数组的定义:一组相同类型元素的集合.

4.1 数组的定义

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };    //定义一个整形数组,最多放10个元素

4.2 数组的下标

C语言规定: 数组的每个元素都有一个下标,下标是从0开始的。数组可以通过下标来访问的。

比如:

int arr[10] = { 0 };
//如果数组10个元素,下标的范围是0-9

4.3 数组的使用

int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int i = 0;while (i < 10){printf("%d ", arr[i]);i = i + 1;}return 0;
}

5. 操作符

C语言提供了许多操作符, 我们经常能看到, C语言是非常灵活的, 这个"灵活"就体现在它提供了非常多的操作符.

算术操作符

+ - * / %
  1. /%的区别:

/是取商, %是取余数.

再比如37÷4=9......1, 其中37是被除数,4是除数,商是9,但有余数1 , 对应的9是/运算结果, 1是%运算结果.
  1. /除号两端都是整数的时候, 执行的是整数除法,如果两端只要有一个浮点数就执行浮点数的除法

  1. %操作符的两个操作符只能是整数

移位操作符

>> <<

位操作符

& ^ |

赋值操作符

= += -= *= /= &= ^= |= >>= <<=

单目操作符

!         逻辑反操作
-         负值
+         正值
&         取地址
sizeof    操作数的类型长度(以字节为单位)
~         对一个数的二进制按位取反
--        前置、后置--
++        前置、后置++
*         间接访问操作符(解引用操作符)
(类型)     强制类型转换
  1. sizeof不是一个函数, 而是一个单目操作符, 用于拿到操作数的类型长度(以字节为单位)

  1. 前置后置++, 前置后置--

  1. (类型) -> 强制类型转换
    int a = 3.14;// 3.14 字面浮点数, 编译器默认理解为 double 类型

所以需要添加强制类型转换操作符.

关系操作符

>
>=
<
<=
!=     用于测试“不相等”
==     用于测试“相等”

逻辑操作符

&&     逻辑与
||     逻辑或

在C语言中,&&(逻辑与)和||(逻辑或)是两个用于组合条件的逻辑运算符。

  1. &&(逻辑与):

&&运算符用于将两个条件组合在一起,只有当两个条件都为真时,整个组合条件才为真。如果任何一个条件为假,整个组合条件就为假。

示例:

#include <stdio.h>int main() {int age = 25;int isStudent = 1;if (age >= 18 && isStudent == 1) {printf("你是成年学生。\n");} else {printf("你不符合条件。\n");}return 0;
}

在上面的例子中,age >= 18isStudent == 1两个条件都必须为真,才会打印"你是成年学生"。如果其中任何一个条件为假,就会打印"你不符合条件"。

  1. ||(逻辑或):

||运算符用于将两个条件组合在一起,只要其中一个条件为真,整个组合条件就为真。只有当两个条件都为假时,整个组合条件才为假。

示例:

#include <stdio.h>int main() {int hasMoney = 0;int hasCreditCard = 1;if (hasMoney == 1 || hasCreditCard == 1) {printf("你有支付手段。\n");} else {printf("你没有支付手段。\n");}return 0;
}

在上面的例子中,hasMoney == 1hasCreditCard == 1两个条件中只要有一个为真,就会打印"你有支付手段"。如果两个条件都为假,才会打印"你没有支付手段"。

总结一下:

&&(逻辑与)要求所有条件都为真才为真。

||(逻辑或)只要有一个条件为真就为真。

条件操作符

exp1 ? exp2 : exp3

条件表达式 `exp1 ? exp2 : exp3` 是C语言中的一种三元运算符,也称为条件运算符或三元条件表达式。它允许你在一个表达式中根据条件的真假来选择执行不同的操作。这个运算符的结构如下:

条件 ? 表达式1 : 表达式2

- 如果条件为真,表达式1将被执行,其结果将成为整个表达式的值。

- 如果条件为假,表达式2将被执行,其结果将成为整个表达式的值。

#include <stdio.h>int main() {int x = 10;int y = 20;int max = (x > y) ? x : y;printf("最大值是:%d\n", max);return 0;
}

逗号表达式

逗号表达式就是逗号隔开的一串表达式, 特点是从左向右依次计算, 整个表达式的结果是最后一个表达式的结果. 其形式如下:

exp1, exp2, exp3, …expN

下标引用, 函数调用和结构成员

[] () . ->
// []
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };arr[3] = 20;    // []就是下标引用操作符    arr和3就是[]的操作数return 0;
}
// 函数调用操作符
int Add(int x, int y)
{return x + y;
}
int main()
{int sum = Add(2, 3);    // ()就是函数调用操作符, Add, 2, 3都是()的操作数return 0;
}

6. 常见关键字

auto break case char const continue default do double else enum
extern float for goto if int long register return short signed
sizeof static struct switch typedef union unsigned void volatile while

C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。

auto: 在现代C语言已经不常用, 最早用于定义自动存储类别的变量.
break: 一般常用在循环结构中, 比如for, while, do while, 也用于选择结构的switch, case选择.
case: 用于switch语句中. 还有default关键字也用于switch语句中.
continue: 也是用于循环的关键字
goto: 实现跳转
char: 是数据类型用于表示字符. 像short, int, long, float, double也都是属于数据类型的. 但是也都是C语言中预定好的关键字.
const: 用于修饰常属性.
enum: 枚举
struct: 结构体
union: 联合体(共用体)
extern: 声明外部符号
register: 寄存器
static: 静态的
signed: 有符号的
unsigned: 无符号的
typedef: 类型重命名
void: 空, 表示无(函数的返回类型, 函数参数)

注意: 变量命名不能使用关键字.

6.1 关键字typedef

typedef 顾名思义是类型定义,这里应该理解为类型重命名.

比如:

typedef unsigned int uint;    // 把 unsigned int 重命名为 uinttypedef struct Node        // 结构体类型, 使用起来很抽象, 不方便. 所以在前面加上typedef, 并在结尾给它起名为Node.
{int data;struct Node* next;
}Node;
int main()
{unsigned int num = 0;    // unsigned int 较长, 输入麻烦uint num2 = 1;struct Node n;    // 正常情况下要这么写, 很抽象Node n2;    // Node 此时就等价于 struct Nodereturn 0;
}

6.2 关键字static

在C语言中:

static是用来修饰变量和函数的

1.修饰局部变量-称为静态局部变量
2.修饰全局变量-称为静态全局变量
3.修饰函数-称为静态函数

我们先来看如下的例子:

void test()
{int a = 1;a++;printf("%d ", a);
}
int main()
{int i = 0;while (i < 10){test();i++;}return 0;
}

分析代码可知,

1. main函数开始执行,初始化整数变量 i 为0。
2. 进入 while循环,条件 i < 10成立,进入循环体。
3. 在循环体内部,调用 test 函数。
4. test函数内部定义了一个整数变量 a,并初始化为1,然后执行 a++,将 a 的值增加到2。
5. 接着,printf 函数打印 a 的值,即2,然后输出一个空格。
6. test 函数执行完毕,返回到 while 循环中,增加 i 的值到1。
7. 回到循环条件,i 仍然小于10,所以继续执行下一轮循环。
8. 重复上述步骤,每次调用 test 函数都会使 a 的值增加到2,然后打印2。
9. 当循环执行10次后,i 的值增加到10,不再满足 i < 10 的条件,循环结束。

因此,代码的执行结果是打印出10个2,而不是10个3。 每次调用 test 函数都会创建一个新的局部变量 a,并且该变量的生命周期仅在函数调用期间 因此,a 的值在每次调用 test 函数时都会重新初始化为1,然后增加到2。

运行结果:


static修饰局部变量

前面提到, static可用于修饰局部变量, 那么我们尝试将其使用到test()中的变量a, 然后来看一下结果会是什么.

分析代码, 关键字static在这里的作用是将变量a变成一个静态局部变量, 它的生存期会持续整个程序的执行过程, 而不是每次函数调用都重新初始化.

总结如下

static修饰局部变量的时候,当局部变量出了作用域是不销毁的. 本质上,static修饰局部变量的时候,会将变量的存储位置进行更改.

我们在学习C/C++的时候, 经常会考虑变量的管理.
在内存中一般分为如下区域:
1. 栈区: 用于存放局部变量(...当然也有其他东西, 这里暂且省略). 栈区中局部变量的特点是进入它的作用域就创建, 离开作用域就销毁.
2. 堆区: 用于动态内存管理, 涉及函数有malloc/free, calloc, realloc等.
3. 静态区: 变量被static修饰之后就会存放于静态区, 成为静态变量. 静态变量则是离开它的作用域 不销毁, 会直至整个程序生命周期结束才销毁. (全局变量也会放在静态区)

所以实质上, 存储位置的改变影响了变量a的生命周期,生命周期变长,和程序的生命周期一样。


static修饰全局变量

前文提到, 可以在{}外部定义全局变量, 那么我们也可以把全局变量定义到外部文件中.

如图, 当我们在add.c这个源文件中创建变量g_val, 此时它就是一个全局变量, 那么要在test.c中使用g_val的话, 就需要使用extern关键字在test.c中进行声明.

那么接下来当我们使用static去修饰g_val这个全局变量时, 上述程序会直接报错.

static int g_val = 2023;

可以看到, 报错:无法解析的外部符号g_val. 虽然g_val已经在test.c中声明了, 但是依然不能使用.

补充: 1. 全局变量是具有外部链接属性; 2. 一个可执行的C程序是需要经过编译 + 链接两个步骤.

那么报错的原因是static修饰全局变量的时候, 全局变量的外部链接属性被更改为内部链接属性, 使得其他源文件(.c)无法再使用到该全局变量.

我们使用的直观感受是 g_val的作用域变小了.

static修饰函数

static修饰函数与static修饰全局变量较为类似

首先依旧是熟悉的加法操作的函数, 只不过这次将它放在add.c中, 并在main()所在文件test.c进行声明.

可以看到, 正常求和并打印了结果. 当它被static修饰之后, 我们来看.

补充: 函数也是具有外部链接属性的
// add.c
static int Add(int x, int y)
{return x + y;
}

可以看到, 报错:无法解析的外部符号Add, 由文件位置可知是链接属性的问题.

所以, 一个函数本来是具有外部链接属性的, 但是被static修饰的时候,外部链接属性就变成了内部链接属性,其他源文件(.c)就无法使用了。


7. #define定义常量和宏

在C和C++中,#define 预处理指令用于定义常量和宏。它的一般语法如下:

#define 常量名 值

或者

#define 宏名(参数列表) 替换文本
  1. 定义常量:

使用 #define 来定义常量可以让你在代码中使用具体的值,这些值在编译时会被替换成代码中的文本。例如:

#define PI 3.14159265

这个定义将创建一个名为 PI 的常量,它在代码中的所有出现都会被替换为 3.14159265

  1. 定义宏:

使用 #define 还可以定义宏,宏是一种带有参数的代码替换机制。例如,你可以定义一个用于交换两个变量值的宏:

#define SWAP(a, b) { int temp = a; a = b; b = temp; }

然后,在你的代码中可以这样使用:

int x = 5, y = 10;
SWAP(x, y);

这将被展开为:

{ int temp = x; x = y; y = temp; }

宏允许你创建一些代码片段的快速替代,但要小心使用,因为它们没有类型检查,可能会导致一些不直观的错误。

注意事项:

  • 常量名通常用大写字母表示,以区分于变量名。

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

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

相关文章

如何实现不同MongoDB实例间的数据复制?

作为一种Schema Free文档数据库&#xff0c;MongoDB因其灵活的数据模型&#xff0c;支撑业务快速迭代研发&#xff0c;广受开发者欢迎并被广泛使用。在企业使用MongoDB承载应用的过程中&#xff0c;会因为业务上云/跨云/下云/跨机房迁移/跨地域迁移、或数据库版本升级、数据库整…

详解混合类型文件(Polyglot文件)的应用生成与检测

1. 引入 混合类型文件&#xff08;Polyglot文件&#xff09;&#xff0c;是指一个文件&#xff0c;既可以是合法的A类型&#xff0c;也可以是合法的B类型。 比如参考3中的文件&#xff0c;是一个html文件&#xff0c;可以用浏览器正常打开&#xff1b;它也是一个一个.jar文件&…

vue项目打包时如何将静态文件打包到一个单独的文件夹

在Vue项目中&#xff0c;你可以使用Webpack的配置来实现将静态文件打包到一个单独的文件夹。下面是一种常见的方法&#xff1a; 在Vue项目的根目录下&#xff0c;创建一个名为static的文件夹&#xff08;如果还没有&#xff09;。这个文件夹将用于存放静态文件。在vue.config.j…

【C++技能树】手撕AVL树 --插入与旋转详解

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 文章目录 0.平衡搜索二叉树概念0.1 平衡因子 1.插入1.1 普通插入操作1.2更新平衡因子 2.旋转2.1 左单旋2.2 右单旋2.3 右左双旋2.4 左右双旋 3. 旋…

openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据

文章目录 openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据 openGauss学习笔记-71 openGauss 数据库管理-创建和管理普通表-删除表中数据 在使用表的过程中&#xff0c;可能会需要删除已过期的数据&#xff0c;删除数据必须从表中整行的删除。 SQL不…

Nodejs 第十六章(ffmpeg)

FFmpeg 是一个开源的跨平台多媒体处理工具&#xff0c;可以用于处理音频、视频和多媒体流。它提供了一组强大的命令行工具和库&#xff0c;可以进行视频转码、视频剪辑、音频提取、音视频合并、流媒体传输等操作。 FFmpeg 的主要功能和特性&#xff1a; 格式转换&#xff1a;…

还没用熟 TypeScript 社区已经开始抛弃了

根据 rich-harris-talks-sveltekit-and-whats-next-for-svelte 这篇文章的报道&#xff0c; Svelte 计划要把代码从 TS 换到 JS 了。 The team is switching the underlying code from TypeScript to JavaScript. That and the update will then allow the team to incorporate…

边缘计算AI智能安防监控视频平台车辆违停算法详解与应用

随着城市车辆保有量呈现高速增长趋势&#xff0c;交通拥堵、违章行为也日益泛滥。因为车辆未停放在指定区域导致的车位浪费、占用/堵塞交通要道、车辆剐蹭等问题层出不穷。通过人工进行违法停车的监控&#xff0c;不仅让监控人员工作负荷越来越大&#xff0c;而且存在发现不及时…

第18章_瑞萨MCU零基础入门系列教程之GPT

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

redis--windows配置--redis基础

写在前面&#xff1a; 文章目录 win安装配置密码配置服务服务已经存在 可视化工具运行类型基础类型 帮助文档命令通用命令string命令hashlistsetsortedset win安装 下载地址 然后一路next就可以了。 记得添加到环境变量 配置密码 在目录打开配置文件 搜索requirepass …

K8S:Yaml文件详解及编写示例

文章目录 一.Yaml文件详解1.Yaml文件格式2.YAML 语法格式 二.Yaml文件编写及相关概念1.查看 api 资源版本标签2.yaml编写案例&#xff08;1&#xff09;相关标签介绍&#xff08;2&#xff09;Deployment类型编写nginx服务&#xff08;3&#xff09;k8s集群中的port介绍&#x…

CS5817规格书|CS5817芯片参数|多功能便携式显示器方案芯片规格

CS5817支持最高4K 60Hz是集睿致远&#xff08;ASL&#xff09; 新推出的多功能显示控制器芯片&#xff0c;CS5817产品可应用于便携显示器、电竞显示器、桌面显示器、一体式台式机和嵌入式显示系统。 Type-C/DP/HDMI2.0输入转LVDS/eDP/VBO 芯片, 高度集成了多种输入输出接口, 并…

Vue的详细教程--入门

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Vue的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Vue是什么 二. Vue的特点及优势 三.使用…

uniapp——实现在线选座功能——技能提升

首先声明一点&#xff1a;下面的内容是从一个uniapp的程序中摘录的&#xff0c;并非本人所写&#xff0c;先做记录&#xff0c;以免后续遇到相似需求抓耳挠腮。 这里写目录标题 效果图代码——html部分cu-custom组件anil-seat组件 代码——jscss部分 效果图 代码——html部分 …

【小沐学CAD】嵌入式UI开发工具:GL Studio

文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ DiSTI 是 HMI 软件、虚拟驾驶舱、仪表、信息娱乐、集群显示器和嵌入式 UI 解决方案的领先提供商。 而它的GL Stu…

芯片工程师求职题目之CPU篇(4)

1. 在组相联cache中&#xff0c;用于替换cache line的算法有哪些&#xff1f; LRU(Least Recently Used)算法&#xff1a;该算法会跟踪每个cache line的age(年龄)情况&#xff0c;并在需要时替换掉近期最少使用的cache line。MRU(Most Recently Used)算法&#xff1a;这与LRU相…

buuctf crypto 【密码学的心声】解题记录

1.打开可以看到一个曲谱 2.看到曲谱中的提示埃塞克码可以想到ascii码&#xff0c;没有八可以联想到八进制&#xff0c;而八进制又对应着三位的二进制&#xff0c;然后写个脚本就好了 oct [111,114,157,166,145,123,145,143,165,162,151,164,171,126,145,162,171,115,165,143,…

Nacos单机启动的两种方式

说明&#xff1a;直接双击nacos的启动脚本&#xff0c;默认是集群&#xff08;cluster&#xff09;的方式&#xff1b; 需要单机启动&#xff0c;有以下两种方式&#xff1b; 方式一&#xff1a;命令行 在当前目录打开命令窗口&#xff0c;输入以下命令启动nacos startup.…

Redis 高性能设计之epoll和IO多路复用深度解析

I/O多路复用模型是什么 I/O&#xff1a;网络I/O多路&#xff1a;多个客户端连接&#xff08;连接就是套接字描述符&#xff0c;即socket或者channel&#xff09;&#xff0c;指的是多条TCP连接复用&#xff1a;用一个进程来处理多条的连接&#xff0c;使用单进程就能的够实现同…

交叉编译工具链-Ubuntu 安装说明

交叉编译工具链-Ubuntu 安装说明 【实验目的】 了解交叉编译工具链的安装方法与使用方法 【实验环境】 1、 ubuntu 14.04 发行版 【注意事项】 1、实验步骤中以“$”开头的命令表示在 ubuntu 环境下执行 【实验步骤】 1、安装交叉编译工具链 在 ubuntu 下打开一个终端并进入到家…