学习网站: C 语言教程 | 菜鸟教程 (runoob.com)C 语言教程 | 菜鸟教程 (runoob.com)C 语言教程 | 菜鸟教程 (runoob.com)
这个网站知识完整,讲解清晰。
在线C语言编程工具:菜鸟教程在线编辑器 (runoob.com)
国外学习网站:C语言介绍 - GeeksforGeeks
算法知识网站:算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn)
0.前言
静态语言和动态语言
**动态语言:**是运行时才确定数据类型的语言,变量在使用之前无需申明类型,通常变量的值是被赋值的那个值的类型。比如Php、Asp、JavaScript、Python、Per等等。
**静态语言:**是编译时变量的数据类型就可以确定的语言,大多数静态语言要求在使用变量之前必须声明数据类型。比如Java、C、C++、C#等。
图片来源:动态语言和静态语言的区别(如python与c++)-CSDN博客
1.C语言的简介
C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的。
1.1特点
- 易学习
- 结构化语言
- 高效率
- 底层处理
- 使用多种计算机
- 通用和便携(General Purpose and Portable)
1.2 C与C++的区别
- C++ 支持 OOP 范式,而 C 只有编程的过程概念。
- C++ 具有异常处理功能。在 C 语言中,我们必须手动解析。
- C 中没有引用。
2 环境配置
教程:从零开始的vscode安装及环境配置教程(C/C++)(Windows系统)_vscode搭建编译器环境-CSDN博客
**C 代码的编辑器 :**VSCode(全称:Visual Studio Code)是一款由微软开发且跨平台的免费源代码编辑器,VSCode 开发环境非常简单易用。
**C 代码的编译器 :**最常用的免费可用的编译器是 GNU 的 C/C++ 编译器。
windows安装编译器:为了在 Windows 上安装 GCC,您需要安装 MinGW。
AI助手:
- GitHub Copilot
- Fitten Code
3、C 程序结构
C程序主要包括以下部分:
- 预处理器指令:#include <stdio.h>
- 函数:int main() 是主函数
- 变量:int a
- 语句&表达式:{里面的}
- 注释:/*...*/
4 C基本语法
4.1 C的令牌
C 程序由各种令牌组成,令牌可以是关键字、标识符、常量、字符串值,或者是一个符号。
4.2 分号
在 C 程序中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。
4.3 注释
两种注释方式
1、单行注释: //
2、/* */ 这种格式的注释可以单行或多行。
4.4 标识符
C 标识符是用来标识变量、函数,或任何其他用户自定义项目的名称。一个标识符以字母 A-Z 或 a-z 或下划线 _ 开始,后跟零个或多个字母、下划线和数字(0-9)。C 标识符内不允许出现标点字符,比如 @、$ 和 %。C 是区分大小写的编程语言。
4.5 常见的关键字
关键字 | 说明 |
---|---|
auto | 声明自动变量 |
break | 跳出当前循环 |
case | 开关语句分支 |
char | 声明字符型变量或函数返回值类型 |
const | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 |
continue | 结束当前循环,开始下一轮循环 |
default | 开关语句中的"其它"分支 |
do | 循环语句的循环体 |
double | 声明双精度浮点型变量或函数返回值类型 |
else | 条件语句否定分支(与 if 连用) |
enum | 声明枚举类型 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 |
float | 声明浮点型变量或函数返回值类型 |
for | 一种循环语句 |
goto | 无条件跳转语句 |
if | 条件语句 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数返回值类型 |
register | 声明寄存器变量 |
return | 子程序返回语句(可以带参数,也可不带参数) |
short | 声明短整型变量或函数 |
signed | 声明有符号类型变量或函数 |
sizeof | 计算数据类型或变量长度(即所占字节数) |
static | 声明静态变量 |
struct | 声明结构体类型 |
switch | 用于开关语句 |
typedef | 用以给数据类型取别名 |
unsigned | 声明无符号类型变量或函数 |
union | 声明共用体类型 |
void | 声明函数无返回值或无参数,声明无类型指针 |
volatile | 说明变量在程序执行中可被隐含地改变 |
while | 循环语句的循环条件 |
4.6、 C语言的数据类型
4.6.1 字、字节(Byte)、比特(bit)
比特bit是二进制位(Binary digit)的简称,一个二进制包含的信息量成为一比特bit。比特bit是计算机内部数据存储的最小单位。二进制在效率和成本方面的优势为全世界所接受,现在电脑所有的信息都是二进制的,就是0和1组成的。
字节Byte是计算机数据处理的最小单位 ,习惯上用大写的B表示,每个字节有8个二进制位,其中最右边的一位为最低位,最左边的一位为最高位,每个二进制位的值不是0就是1。一个字节由8个二进制位组成。也就是1字节Byte等于8比特Bit。
字和字节都是计算机的存储单元 。++字由若干个字节组成,一个字节是8个比特bit。字的位数叫做字长,即cpu一次处理二进制代码的位数++ 。字的长度与计算架构有关,比如32位机,一个字就是32位,换算成字节就是4字节;同样的64位机,一个字就是64位,也就是8字节。字也是计算机一次处理数据的最大单位。
序号 | 类型与描述 |
---|---|
1 | 基本数据类型 它们是算术类型,包括整型(int)、字符型(char)、浮点型(float)和双精度浮点型(double)。 |
2 | 枚举类型: 它们也是算术类型,被用来定义在程序中只能赋予其一定的离散整数值的变量。 |
3 | void 类型: 类型说明符 void 表示没有值的数据类型,通常用于函数返回值。 |
4 | 派生类型: :包括数组类型、指针类型和结构体类型。 |
数组类型和结构类型统称为聚合类型。函数的类型指的是函数返回值的类型。
4.6.2 整数类型
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1 字节 | -128 到 127 或 0 到 255(ASIICA) |
unsigned char | 1 字节 | 0 到 255 |
signed char | 1 字节 | -128 到 127 |
int | 2 或 4 字节 | -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647 |
unsigned int | 2 或 4 字节 | 0 到 65,535 或 0 到 4,294,967,295 |
short | 2 字节 | -32,768 到 32,767 |
unsigned short | 2 字节 | 0 到 65,535 |
long | 4 字节 | -2,147,483,648 到 2,147,483,647 |
unsigned long | 4 字节 | 0 到 4,294,967,295 |
注意,各种类型的存储大小与系统位数有关,但目前通用的以64位系统为主。
为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。
4.6.3 浮点类型
下表列出了关于标准浮点类型的存储大小、值范围和精度的细节:
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4 字节 | 1.2E-38 到 3.4E+38 | 6 位有效位 |
double | 8 字节 | 2.3E-308 到 1.7E+308 | 15 位有效位 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 | 19 位有效位 |
头文件 float.h 定义了宏,在程序中可以使用这些值和其他有关实数二进制表示的细节。
4.6.4 void 类型
序号 | 类型与描述 |
---|---|
1 | 函数返回为空 C 中有各种函数都不返回值,或者您可以说它们返回空。不返回值的函数的返回类型为空。例如 void exit (int status); |
2 | 函数参数为空 C 中有各种函数不接受任何参数。不带参数的函数可以接受一个 void。例如 int rand(void); |
3 | 指针指向 void 类型为 void * 的指针代表对象的地址,而不是类型。例如,内存分配函数 void *malloc( size_t size ); 返回指向 void 的指针,可以转换为任何数据类型。 |
4.6.5 类型转换
类型转换是将一个数据类型的值转换为另一种数据类型的值。
C 语言中有两种类型转换:
-
**隐式类型转换:**隐式类型转换是在表达式中自动发生的,无需进行任何明确的指令或函数调用。它通常是将一种较小的类型自动转换为较大的类型,例如,将int类型转换为long类型或float类型转换为double类型。隐式类型转换也可能会导致数据精度丢失或数据截断。
-
**显式类型转换:**显式类型转换需要使用强制类型转换运算符(type casting operator),它可以将一个数据类型的值强制转换为另一种数据类型的值。强制类型转换可以使程序员在必要时对数据类型进行更精确的控制,但也可能会导致数据丢失或截断。
4.7 C变量基本变量
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的
类型 | 描述 |
---|---|
char | 通常是一个字节(八位), 这是一个整数类型。 |
int | 整型,4 个字节,取值范围 -2147483648 到 2147483647。 |
float | 单精度浮点值。单精度是这样的格式,1位符号,8位指数,23位小数。 |
double | 双精度浮点值。双精度是1位符号,11位指数,52位小数。 |
void | 表示类型的缺失。 |
4.7.1 变量定义
type value
type 表示变量的数据类型,可以是整型、浮点型、字符型、指针等,也可以是用户自定义的对象。
variable_list 可以由一个或多个变量的名称组成,多个变量之间用逗号,分隔,变量由字母、数字和下划线组成,且以字母或下划线开头。
比如:
- int age;
- char grade;
- int i,j,k;
- >>>
4.7.2 变量初始化
type variable_name = value;
其中,type 表示变量的数据类型,variable_name 是变量的名称,value 是变量的初始值。
4.7.3 后续初始化变量
type variable_name; // 变量定义
variable_name = new_value; // 变量初始化
**注意:**为了避免不确定的行为和错误,建议在使用变量之前进行初始化。
4.7.4 变量不初始化
对于全局变量和静态变量(在函数内部定义的静态变量和在函数外部定义的全局变量),它们的默认初始值为零。
以下是不同类型的变量在没有显式初始化时的默认值:
- 整型变量(int、short、long等):默认值为0。
- 浮点型变量(float、double等):默认值为0.0。
- 字符型变量(char):默认值为'\0',即空字符。
- 指针变量:默认值为NULL,表示指针不指向任何有效的内存地址。
- 数组、结构体、联合等复合类型的变量:它们的元素或成员将按照相应的规则进行默认初始化,这可能包括对元素递归应用默认规则。
需要注意的是,局部变量(在函数内部定义的非静态变量)不会自动初始化为默认值,它们的初始值是未定义的(包含垃圾值)。因此,在使用局部变量之前,应该显式地为其赋予一个初始值。
4.7.5 变量声明
变量的声明有两种情况:
- 1、一种是需要建立存储空间的。例如:int a 在声明的时候就已经建立了存储空间。
- 2、另一种是不需要建立存储空间的,通过使用extern关键字声明变量名而不定义它。 例如:extern int a 其中变量 a 可以在别的文件中定义的。
- 除非有extern关键字,否则都是变量的定义。
4.8 C 常量
常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。
常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值,也有枚举常量。
4.8.1 整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,不带前缀则默认表示十进制。
整数常量也可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
4.8.2 字符常量
字符常量是括在单引号中,例如,'x' 可以存储在 char 类型的简单变量中。
转义序列 | 含义 |
---|---|
\\ | \ 字符 |
\' | ' 字符 |
\" | " 字符 |
\? | ? 字符 |
\a | 警报铃声 |
\b | 退格键 |
\f | 换页符 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
4.8.3 字符串常量
字符串字面值或常量是括在双引号 " " 中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。
4.8.4 定义常量
在 C 中,有两种简单的定义常量的方式:
- 使用 #define 预处理器: #define 可以在程序中定义一个常量,它在编译时会被替换为其对应的值。
- 使用 const 关键字:const 关键字用于声明一个只读变量,即该变量的值不能在程序运行时修改。
#define 预处理器:#define 常量名 常量值 -> #define PI 3.14159
const 关键字:const 数据类型 常量名 = 常量值; -> const int MAX_VALUE = 100;
**注意:**建议使用 const 关键字来定义常量,因为它具有类型检查和作用域的优势,而 #define 仅进行简单的文本替换,可能会导致一些意外的问题。
4.9 存储类
存储类定义 C 程序中变量/函数的存储位置、生命周期和作用域。
这些说明符放置在它们所修饰的类型之前。
下面列出 C 程序中可用的存储类:
- auto
- register
- static
- extern
4.9.1 auto类
auto 存储类是所有局部变量默认的存储类。
定义在函数中的变量默认为 auto 存储类,这意味着它们在函数开始时被创建,在函数结束时被销毁。
4.9.2 register 存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。register 存储类定义存储在寄存器,所以变量的访问速度更快,但是它不能直接取地址,因为它不是存储在 RAM 中的。在需要频繁访问的变量上使用 register 存储类可以提高程序的运行速度。
cpp
register int miles;
4.9.3 static 存储类
cs
static int count=10; /* 全局变量 - static 是默认的 */
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。
静态变量在程序中只被初始化一次,即使函数被调用多次,该变量的值也不会重置。
4.9.4 extern 存储类
cs
extern void write_extern();
extern 存储类用于定义在其他文件中声明的全局变量或函数。当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义。
4.10 运算符
在 C 语言中,运算符是表示要对一个或多个操作数执行的操作的符号。它们是 C 编程的基本组件
运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符,并提供了以下类型的运算符:
C 语言提供了广泛的运算符,根据其功能可以分为 6 种类型:
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 杂项运算符
4.10.1 算术运算符
The arithmetic operators are used to perform arithmetic/mathematical operations on operands. There are 9 arithmetic operators in C language(算术运算符用于对操作数执行算术/数学运算。C语言中有9个算术运算符:
| S.No. | Symbol | Operator | Description | Syntax |
| 1 | + | Plus | Adds two numeric values. 把两个操作数相加 | a + b |
| 2 | -- | Minus | Subtracts right operand from left operand.第一个操作数减第二个操作数 | a -- b |
| 3 | * | Multiply | Multiply two numeric values.两个操作数相乘 | a * b |
| 4 | / | Divide | Divide two numeric values. 第一个操作数除以第二个操作数 | a / b |
| 5 | % | Modulus | Returns the remainder after diving the left operand with the right operand. 返回左操作数除以右操作数后的余数。 | a % b |
| 6 | + | Unary Plus | Used to specify the positive values.用于指定正值。 | +a |
| 7 | -- | Unary Minus | Flips the sign of the value. 翻转值的符号。 | -a |
| 8 | ++ | Increment | Increases the value of the operand by 1. 将操作数的值增加1 | a++ |
9 | --- | Decrement | Decreases the value of the operand by 1. 将操作数的值减少1。 | a-- |
---|
4.10.2 关系运算符(Logical Operator)
C 中的关系运算符用于比较两个操作数。所有这些运算符都是二进制运算符,它们作为比较的结果返回真值或假值。(The relational operators in C are used for the comparison of the two operands. All these operators are binary operators that return true or false values as the result of comparison.)
运算符 | 描述 | 实例 |
---|---|---|
== | 检查两个操作数的值是否相等,如果相等则条件为真。 | (A == B) 为假。 |
!= | 检查两个操作数的值是否相等,如果不相等则条件为真。 | (A != B) 为真。 |
> | 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 | (A > B) 为假。 |
< | 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 | (A < B) 为真。 |
>= | 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 | (A >= B) 为假。 |
<= | 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 | (A <= B) 为真。 |
cs
// C program to illustrate the relational operators
#include <stdio.h>
int main()
{
int a = 25, b = 5;
// using operators and printing results
printf("a < b : %d\n", a < b);
printf("a > b : %d\n", a > b);
printf("a <= b: %d\n", a <= b);
printf("a >= b: %d\n", a >= b);
printf("a == b: %d\n", a == b);
printf("a != b : %d\n", a != b);
return 0;
}
4.10.3 C 语言中的逻辑运算符
逻辑运算符用于组合两个或多个条件/约束,或补充所考虑的原始条件的评估。逻辑运算符操作的结果是一个布尔值,可以是 true 或 false。
运算符 | 描述 | 实例 |
---|---|---|
&& | 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 | (A && B) 为假。 |
|| | 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 | (A || B) 为真。 |
! | 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 | !(A && B) 为真。 |
cs
// C program to illustrate the logical operators
#include <stdio.h>
int main()
{
int a = 25, b = 5;
// using operators and printing results
printf("a && b : %d\n", a && b);
printf("a || b : %d\n", a || b);
printf("!a: %d\n", !a);
return 0;
}
4.10.4 位运算符(Bitwise Operators)
按位运算符用于对操作数执行位级操作。首先将运算符转换为位级,然后对操作数执行计算。加法、减法、乘法等数学运算可以在位级别执行,以加快处理速度。
| S.No. | Symbol | Operator | Description | Syntax |
| 1 | & | ****Bitwise AND/****按位与 | Performs bit-by-bit AND operation and returns the result./对两个操作数的每一位执行逻辑与操作。 **解释:**如果两个相应的位都为 1,则结果为 1,否则为 0。 > 0&0=0; > 0&1=0; > 1&0=0; > 1&1=1; | a & b |
| 2 | | | ****Bitwise OR/****按位或 | Performs bit-by-bit OR operation and returns the result./对两个操作数的每一位执行逻辑或操作。 **解释:**如果两个相应的位都为 0,则结果为 0,否则为 1。 > 0|0=0; > 0|1=1; > 1|0=1; > 1|1=1; | a | b |
| 3 | ^ | ****Bitwise XOR/****按位异或 | Performs bit-by-bit XOR operation and returns the result./对两个操作数的每一位执行逻辑异或操作。 **解释:**如果两个相应的位值相同,则结果为 0,否则为 1。 > 0^0=0; > 0^1=1; > 1^0=1; > 1^1=0; | a ^ b |
| 4 | ~ | ****Bitwise First Complement/****逐位第一补码 | Flips all the set and unset bits on the number./ 对操作数的每一位执行逻辑取反操作。 **解释:**即将每一位的 0 变为 1,1 变为 0。 > ~1=-2; > ~0=-1; | ~a |
| 5 | << | ****Bitwise Leftshift/****逐位左移 | Shifts the number in binary form by one place in the operation and returns the result./将操作数的所有位向左移动指定的位数。左移 n 位相当于乘以 2 的 n 次方。 | a << b |
6 | >> | ****Bitwise Rightshilft/****逐位右移 | Shifts the number in binary form by one place in the operation and returns the result./ 将操作数的所有位向右移动指定的位数。右移n位相当于除以 2 的 n 次方。 | a >> b |
---|
4.10.5 赋值运算符(Assignment Operators)
赋值运算符用于为变量赋值。赋值运算符左侧的操作数是变量,右侧的操作数是值。右侧的值必须与左侧的变量属于相同的数据类型,否则编译器会报错。
赋值运算符可以与 C 中的其他运算符组合使用,从而使用单个运算符提供多项运算。这些运算符称为复合运算符。
运算符 | 描述 | 实例 |
---|---|---|
= | 简单的赋值运算符,把右边操作数的值赋给左边操作数 | C = A + B 将把 A + B 的值赋给 C |
+= | 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 | C += A 相当于 C = C + A |
-= | 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 | C -= A 相当于 C = C - A |
*= | 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 | C *= A 相当于 C = C * A |
/= | 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 | C /= A 相当于 C = C / A |
%= | 求模且赋值运算符,求两个操作数的模赋值给左边操作数 | C %= A 相当于 C = C % A |
<<= | 左移且赋值运算符 | C <<= 2 等同于 C = C << 2 |
>>= | 右移且赋值运算符 | C >>= 2 等同于 C = C >> 2 |
&= | 按位与且赋值运算符 | C &= 2 等同于 C = C & 2 |
^= | 按位异或且赋值运算符 | C ^= 2 等同于 C = C ^ 2 |
|= | 按位或且赋值运算符 | C |= 2 等同于 C = C | 2 |
cs
// C program to illustrate the arithmatic operators
#include <stdio.h>
int main()
{
int a = 25, b = 5;
// using operators and printing results
printf("a = b: %d\n", a = b);
printf("a += b: %d\n", a += b);
printf("a -= b: %d\n", a -= b);
printf("a *= b: %d\n", a *= b);
printf("a /= b: %d\n", a /= b);
printf("a %= b: %d\n", a %= b);
printf("a &= b: %d\n", a &= b);
printf("a |= b: %d\n)", a |= b);
printf("a >>= b: %d\n", a >> b);
printf("a <<= b: %d\n", a << b);
return 0;
}
4.10.6 其它运算符(other Operators)
C 语言中还有一些其他运算符可用于执行某些特定任务。
运算符 | 描述 | 实例 |
---|---|---|
sizeof() | 返回变量的大小。 | sizeof(a) 将返回 4,其中 a 是整数。 |
& | 返回变量的地址。 | &a; 将给出变量的实际地址。 |
* | 指向一个变量。 | *a; 将指向一个变量。 |
? : | 条件表达式 | 如果条件为真 ? 则值为 X : 否则值为 Y |
点 (.) 和箭头 (->) 运算符:
- 成员运算符用于引用类、结构和联合的单个成员。
- 点运算符应用于实际对象。
- 箭头运算符与指向对象的指针一起使用。
4.10.7 C 中的一元、二元和三元运算符
运算符还可以根据其处理的操作数数量分为三种类型:
- ****一元运算符:****处理单个操作数的运算符。
- ****二进制运算符:****处理两个操作数的运算符。
- ****三元运算符:****处理三个操作数的运算符。
4.10.8 C 中的运算符优先级和关联性
运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。
将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。
C 中的运算符优先级
运算符优先级 确定当表达式具有多个运算符时,首先计算哪个运算符。例如,100-2 * 30
将产生 40,因为它被求值为100 - (2 * 30)
而不是(100-2)* 30
。原因是乘法*
的优先级高于减法(-
)。
C 中的关联性
是指当表达式中有两个或多个具有相同优先级的运算符时,这些运算符的执行顺序。例如,乘法和除法算术运算符具有相同的优先级,假设我们有一个表达式5 * 2/10
,这个表达式将被计算为(5 * 2)/ 10
,因为这些运算符的关联性是从左到右。类似地,20/2 * 5
将被计算为(20/2)*5
。
类别 | 运算符 | 结合性 |
---|---|---|
后缀 | () [] -> . ++ - - | 从左到右 |
一元 | + - ! ~ ++ - - (type)* & sizeof | 从右到左 |
乘除 | * / % | 从左到右 |
加减 | + - | 从左到右 |
移位 | << >> | 从左到右 |
关系 | < <= > >= | 从左到右 |
相等 | == != | 从左到右 |
位与 AND | & | 从左到右 |
位异或 XOR | ^ | 从左到右 |
位或 OR | | | 从左到右 |
逻辑与 AND | && | 从左到右 |
逻辑或 OR | || | 从左到右 |
条件 | ?: | 从右到左 |
赋值 | = += -= *= /= %=>>= <<= &= ^= |= | 从右到左 |
逗号 | , | 从左到右 |
4.11 判断
C 语言中条件语句的类型(Types of Conditional Statements in C)
- if 语句(Statement)
- if-else 语句
- 嵌套(Nested) if 语句
- if-else-if 梯子
- switch 语句
- 条件运算符------ ? : 运算符(三元运算符)
- 跳转语句:
- break
- continue
- goto
- return
if-else-if 梯子流程图
switch 语句流程图
条件运算符
(condition) ? \[true_statements\] : \[false_statements\];
break
continue
4.12 C语言中的循环(C -- Loops)
Loops in programming are used to repeat a block of code until the specified condition is met. A loop statement allows programmers to execute a statement or group of statements multiple times without repetition of code.--编程中的循环用于重复代码块,直到满足指定的条件。循环语句允许程序员多次执行一个语句或一组语句,而无需重复代码
There are mainly two types of loops(循环) in C:
- 入口(Entry)控制回路: 在入口控制回路中,在进入回路主体之前检查测试条件。For 循环和 While 循环是 Entry 控制的循环。
- 退出受控循环: 在出口控制回路中,测试条件在回路主体的末尾进行评估。循环体将至少执行一次,无论条件是真还是假。do-while 循环是 Exit。
循环类型 | 描述 |
---|---|
while 循环 | 当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。 |
for 循环 | 多次执行一个语句序列,简化管理循环变量的代码。 |
do...while 循环 | 除了它是在循环主体结尾测试条件外,其他与 while 语句类似。 |
嵌套循环 | 您可以在 while、for 或 do..while 循环内使用一个或多个循环。 |
for 循环(Loop)
**Syntax(**语法):
for (initialize expression(初始化表达式); test expression(测试表达式); update expression(更新表达式)) { // // body of for loop // }
example:
cs
for(int i = 0; i < n; ++i)
{
printf("Body of for loop which will execute till n");
}
While 循环(Loop)
语法(Syntax):
initialization_expression; while (test_expression) { // body of the while loop update_expression; }
Example:
cs
// C program to illustrate
// while loop
#include <stdio.h>
// Driver code
int main()
{
// Initialization expression
int i = 2;
// Test expression
while(i < 10)
{
// loop body
printf( "Hello World\n");
// update expression
i++;
}
return 0;
}
do-while 循环
循环主体都将至少执行一次。
Syntax:
initialization_expression; do { // body of do-while loop update_expression; } while (test_expression);
Example:
cs
// C program to illustrate
// do-while loop
#include <stdio.h>
// Driver code
int main()
{
// Initialization expression
int i = 2;
do
{
// loop body
printf( "Hello World\n");
// Update expression
i++;
// Test expression
} while (i < 1);
return 0;
}
循环控制语句
循环控制语句改变你代码的执行顺序。通过它你可以实现代码的跳转。
C 提供了下列的循环控制语句。点击链接查看每个语句的细节。
控制语句 | * 描述 |
---|---|
break 语句 | 终止循环 或 switch 语句,程序流将继续执行紧接着循环或 switch 的下一条语句。 |
continue 语句 | 告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。 |
goto 语句 | 将控制转移到被标记的语句。但是不建议在程序中使用 goto 语句。 |
4.13 函数(Function)
C 中的函数 是一组语句,调用时执行某些特定任务。它是 C 程序的基本构建块,提供模块化和代码可重用性。函数的编程语句括在****{ } 括号****内,具有特定含义并执行特定操作。在其他语言中,它们也称为子例程或过程。
接下来将学习函数、函数定义、声明、参数和形参、返回值等等。
函数的组成包括:
- 返回类型: 一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
- **函数名称:**这是函数的实际名称。函数名和参数列表一起构成了函数签名。
- **参数:**参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
- **函数主体:**函数主体包含一组定义函数执行任务的语句。
4.13.1 函数的声明(Declarations)
语法(Syntax)
return_type name_of_the_function(parameter_1, parameter_2);
注意:声明函数时,参数名称不是强制性的。我们也可以不使用数据变量的名称来声明函数。
4.13.2 函数的定义
4.13.3 函数的调用
注意: 函数调用是将程序控制带到函数定义处的必要操作。如果没有调用,函数语句将不会被执行。
代码示例:
cs
// C program to show function
// call and definition
#include <stdio.h>
// Function that takes two parameters
// a and b as inputs and returns
// their sum
int sum(int a, int b)
{
return a + b;
}
// Driver code
int main()
{
// Calling sum function and
// storing its value in add variable
int add = sum(10, 30);
printf("Sum is: %d", add);
return 0;
}
4.13.4 函数类型
1、库函数
库函数也称为****"内置函数"**** 。编译器包中已经包含这些函数,每个函数都有特定含义,并包含在包中。内置函数的优点是无需定义即可直接使用,而用户定义函数必须在使用前声明和定义。
比如:
pow()、sqrt()、strcmp()、strcpy() 等。
C 库函数的优点
- C 库函数易于使用且经过优化,性能更佳。
- C 库函数节省了大量时间,即函数开发时间。
- C 库函数很方便,因为它们总是有效。
2、用户定义的函数
程序员创建的函数称为用户定义函数或****"定制函数"**** 。用户定义函数可以根据程序员的需求进行改进和修改。
用户定义函数的优点
- 可变功能可以根据需要进行修改。
- 这些函数的代码可以在其他程序中重复使用。
- 这些功能易于理解、调试和维护。
4.13.5 函数参数类型
调用函数时传递的数据称为实际参数。
形式参数是函数声明中提到的变量和数据类型。
两种方式向 C 函数传递参数:
- 按值传递
此方法中的参数传递将值从实际参数复制到形式函数参数中。因此,函数内部所做的任何更改都不会反映在调用者的参数中。
- 通过引用传递(指针)
调用者的实际参数和函数的实际参数指向相同的位置,因此函数内部所做的任何更改都会反映在调用者的实际参数中。
C语言函数的不足:
- 无法返回多个值。
- 由于堆栈帧分配和程序控制传输而导致的内存和时间开销。
4.14 C语言的作用规则
C 语言中有三个地方可以声明变量:
- 在函数或块内部的局部变量
- 在所有函数外部的全局变量
- 在形式参数的函数参数定义中
4.14.1 局部变量
在某个函数或块的内部声明的变量称为局部变量。它们只能被该函数或该代码块内部的语句使用。局部变量在函数外部是不可知的。下面是使用局部变量的实例。在这里,所有的变量 a、b 和 c 是 main() 函数的局部变量。
cs
#include <stdio.h>
int main ()
{
/* 局部变量声明 */
int a, b;
int c;
/* 实际初始化 */
a = 10;
b = 20;
c = a + b;
printf ("value of a = %d, b = %d and c = %d\n", a, b, c);
return 0;
}
4.14.2 全局变量
全局变量在整个程序生命周期内都是有效的,在任意的函数内部能访问全局变量。全局变量可以被任何函数访问。也就是说,全局变量在声明后整个程序中都是可用的。
cs
#include <stdio.h>
/* 全局变量声明 */
int g;
int main ()
{
/* 局部变量声明 */
int a, b;
/* 实际初始化 */
a = 10;
b = 20;
g = a + b;
printf ("value of a = %d, b = %d and g = %d\n", a, b, g);
return 0;
}
在程序中,局部变量和全局变量的名称可以相同,但是在函数内,如果两个名字相同,会使用局部变量值,全局变量不会被使用。
cs
#include <stdio.h>
/* 全局变量声明 */
int g = 20;
int main ()
{
/* 局部变量声明 */
int g = 10;
printf ("value of g = %d\n", g);
return 0;
}
4.14.3 形式参数
函数的参数,形式参数,被当作该函数内的局部变量,如果与全局变量同名它们会优先使用。下面是一个实例:
cs
#include <stdio.h>
/* 全局变量声明 */
int a = 20;
int main ()
{
/* 在主函数中的局部变量声明 */
int a = 10;
int b = 20;
int c = 0;
int sum(int, int);
printf ("value of a in main() = %d\n", a);
c = sum( a, b);
printf ("value of c in main() = %d\n", c);
return 0;
}
/* 添加两个整数的函数 */
int sum(int a, int b)
{
printf ("value of a in sum() = %d\n", a);
printf ("value of b in sum() = %d\n", b);
return a + b;
}
结果:
value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30
注意:
全局变量与局部变量在内存中的区别:
- 全局变量保存在内存的全局存储区中,占用静态的存储单元;
- 局部变量保存在栈中,只有在所在函数被调用时才动态地为变量分配存储单元。