C_Note
C _Base Grammars
基础语法
C_Language ? Cat_Language!!!
标准代码架构
1 |
|
常量
常量在设置后是不能更改的
C语言中的常量可以根据其类型分为以下几类:
常量类型 | 描述 | 示例 |
---|---|---|
整型常量 | 表示整数的常量,可以是十进制、八进制、十六进制表示。 | 100 , 0123 (八进制), 0x1A (十六进制) |
浮点常量 | 表示小数的常量,包括科学计数法。 | 3.14 , 1.0e-2 |
字符常量 | 表示单个字符的常量,必须用单引号包围。 | 'A' , '9' , '\n' |
字符串常量 | 表示一串字符的常量,必须用双引号包围。 | "Hello" , "C语言" |
符号常量 | 用#define 或const 关键字定义的具有固定值的标识符常量。 |
#define PI 3.14 |
1 | //全局常量 |
变量
变量类型 | 描述 | 范围(根据实现) | 示例 |
---|---|---|---|
int |
整型变量,用于存储整数。 | -32,768 到 32,767 (16位系统),较常见是32位系统 | int x = 5; |
float |
单精度浮点数,用于存储小数。 | 约为 ±3.4e–38 到 ±3.4e+38 | float y = 3.14; |
double |
双精度浮点数,表示更大范围和更精确的小数。 | ±1.7e–308 到 ±1.7e+308 | double z = 2.71828; |
char |
字符变量,存储单个字符(ASCII码)。 | -128 到 127 | char c = 'A'; |
long |
长整型,存储更大的整数。 | -2^31 到 2^31-1 (32位系统) | long n = 1000000; |
short |
短整型,存储较小的整数。 | -32,768 到 32,767 | short s = 32767; |
unsigned |
无符号整型,用于存储非负数。 | 0 到 65535 (16位系统) | unsigned int u = 5; |
1 | //变量 |
注意,在C语言中当变量被定义后它的类型就无法改变了,上文的(float)i
应被视为一种将i
转换为float形式的新的临时变量的表达式
C语言中的混合运算以float f = i/2;
为例,他的结果数据类型和运算数据类型是分开的,流程上来讲是先判断操作数的数据类型,当左右操作数均为整形时执行整形计算,其他情况执行浮点运算,此时得出的结果为int类型数据,随后将结果返回变量f
时被转换为float类型
下面是 C 语言中常用的变量类型的表格展示,包括每种类型的描述、占用的内存大小以及表示的范围
数据类型 | 描述 | 大小(通常) | 范围 |
---|---|---|---|
int |
整数类型,表示带符号的整型数据 | 4 字节(考试可能会问) | -2,147,483,648 到 2,147,483,647 |
unsigned int |
无符号整数类型 | 4 字节 | 0 到 4,294,967,295 |
short |
短整型,带符号 | 2 字节 | -32,768 到 32,767 |
unsigned short |
无符号短整型 | 2 字节 | 0 到 65,535 |
long |
长整型,带符号 | 8 字节 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
unsigned long |
无符号长整型 | 8 字节 | 0 到 18,446,744,073,709,551,615 |
float |
单精度浮点型,用于表示小数 | 4 字节 | 3.4E-38 到 3.4E+38(6 位有效数字) |
double |
双精度浮点型,用于表示高精度小数 | 8 字节 | 1.7E-308 到 1.7E+308(15 位有效数字) |
char |
字符类型,用于表示单个字符 | 1 字节 | -128 到 127(或 0 到 255,取决于系统) |
unsigned char |
无符号字符类型 | 1 字节 | 0 到 255 |
long double |
扩展精度浮点型 | 16 字节 | 3.4E-4932 到 1.1E+4932(18-19 位有效数字) |
_Bool |
布尔类型(C99 引入),表示真或假 | 1 字节 | 0(假)或 1(真) |
void |
无类型,通常用于函数返回类型和指针类型 | 无 | 无法表示数据 |
标准输出指令
prtinf( )
1 |
|
puts( )
输出一个字符串到标准输出(通常是显示器)。puts()
会自动在输出的字符串末尾加上一个换行符
int puts(const char *str);
- 参数
str
是要输出的字符串。 - 返回值为非负整数,表示写入的字符数量。如果发生错误,返回
EOF
(即 -1)。
1 |
|
常用格式说明符
格式说明符 | 描述 | 示例 |
---|---|---|
%d |
以 十进制形式输出带符号整数 | printf("%d", 123); => 123 |
%i |
以 十进制形式输出带符号整数(与 %d 相同) |
printf("%i", 123); => 123 |
%u |
以 十进制形式输出无符号整数 | printf("%u", 123); => 123 |
%f |
以 浮点数形式输出 | printf("%f", 3.14); => 3.140000 |
%e |
以 科学计数法形式输出浮点数 | printf("%e", 123.45); => 1.234500e+02 |
%g |
自动选择使用 %e 或 %f 格式 |
printf("%g", 123.45); => 123.45 |
%c |
输出单个字符 | printf("%c", 'A'); => A |
%s |
输出字符串 | printf("%s", "Hello"); => Hello |
%x |
以 小写十六进制形式输出无符号整数 | printf("%x", 255); => ff |
%X |
以 大写十六进制形式输出无符号整数 | printf("%X", 255); => FF |
%o |
以 八进制形式输出无符号整数 | printf("%o", 255); => 377 |
%p |
输出指针的值(地址) | printf("%p", &a); => 0x7ff... |
%% |
输出百分号 % 本身 |
printf("%%"); => % |
其他格式化修饰符
修饰符 | 描述 | 示例 |
---|---|---|
- |
左对齐(默认右对齐) | printf("%-10d", 123); => 123 |
+ |
强制输出数值符号(正数显示 + 号) |
printf("%+d", 123); => +123 |
|
正数前输出空格,负数前输出 - 号 |
printf("% d", 123); => 123 |
0 |
用零填充(通常用于数字) | printf("%04d", 5); => 0005 |
# |
对于 %o 、%x 或 %X ,显示进制前缀 |
printf("%#x", 255); => 0xff |
数字 | 最小字段宽度 | printf("%5d", 12); => 12 |
.数字 |
精度控制,用于浮点数 | printf("%.2f", 3.14159); => 3.14 |
标准读取函数
1.scanf( )
scanf
是 C 语言中用于从标准输入(通常是键盘)读取数据的函数。它可以根据指定的格式字符串,将输入的内容转换为对应的变量值,但他在Visual Studio 2022已被弃用,改用更安全的scanf_s
scanf_s
是 scanf
的安全版本,要求为字符串输入提供额外的参数,指定缓冲区的大小,以防止缓冲区溢出。在传入数组时缓冲区大小需要和数组长度相等,否者会出现致命bug, (unsigned)sizeof(a)
是常用的自主获取组长度的方法,传入单个数字时则不需要额外参数
scanf_s
向参数传入数据时实际是向该数据的内存地址传值,因此需写为&变量名
1 |
|
关于混合传值
scanf通常读数读到空格就会中断,因此一次向多个变量传值使用空格来中断第一个传值过程,再次输入则向下一个变量传值
2.gets( )
用于获取一行的输入,遇到\n时中断,但gets()
函数不安全,因为它没有检查缓冲区的大小。输入的字符串如果超过数组大小,可能会导致缓冲区溢出,带来严重的安全漏洞。因此,gets()
已经在 C11 标准中被废弃,不推荐使用。
由于 gets()
存在安全性问题,通常建议使用更安全的替代函数 fgets()
:
fgets(str, sizeof(str), stdin)
:str
是字符数组,sizeof(str)
表示最多读取的字符数,stdin
是标准输入流。fgets()
会在读取到换行符或者到达指定字符数时停止
1 | //gets&fgets |
sp : get( )在获取字符串并传给数组时会自动在末尾加上\0
格式说明符
scanf
函数根据 格式说明符 将输入的字符转换为相应的数据类型。以下是常用的格式说明符:
数据类型 | 格式说明符 | 示例代码 | 示例输入 | 说明 |
---|---|---|---|---|
int |
%d |
scanf_s("%d", &num); |
123 | 读取一个十进制整数。 |
float |
%f |
scanf_s("%f", &flt); |
3.14 | 读取一个浮点数。 |
double |
%lf |
3.1415 | 读取一个双精度浮点数。 | |
char |
%c |
scanf_s(" %c", &ch); |
A | 读取一个字符(包括空白字符)。 |
字符串 | %s |
scanf_s("%s", str,(unsigned)sizeof(str)); |
hello | 读取字符串,遇到空白符停止。 |
无符号整数 | %u |
123 | 读取一个无符号整数。 | |
八进制整数 | %o |
017 | 读取一个八进制整数。 | |
十六进制整数 | %x |
0x1F | 读取一个十六进制整数。 | |
长整数 | %ld |
123456 | 读取一个长整型变量。 | |
长长整数 | %lld |
12345678 | 读取一个长长整型变量。 | |
指针 | %p |
0x7ffee | 读取一个指针类型的地址。 |
运算符
1. 算术运算符
算术运算符用于执行基本的数学运算,如加法、减法、乘法、除法等。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
+ |
加法 | a + b |
a 与 b 相加 |
- |
减法 | a - b |
a 减去 b |
* |
乘法 | a * b |
a 乘以 b |
/ |
除法 | a / b |
a 除以 b |
% |
取模(余数) | a % b |
a 除以 b 的余数 |
++ |
自增 | ++a 或 a++ |
a 递增 1 |
-- |
自减 | --a 或 a-- |
a 递减 1 |
++a
和a++
:前者是前置自增(先加再用),后者是后置自增(先用再加)。--a
和a--
:类似地,分别为前置和后置自减。
2. 关系运算符
1 |
|
关系运算符用于比较两个操作数,结果返回布尔值 1
(真)或 0
(假)。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
== |
等于 | a == b |
如果 a 等于 b ,返回 1 ;否则返回 0 |
!= |
不等于 | a != b |
如果 a 不等于 b ,返回 1 ;否则返回 0 |
> |
大于 | a > b |
如果 a 大于 b ,返回 1 ;否则返回 0 |
< |
小于 | a < b |
如果 a 小于 b ,返回 1 ;否则返回 0 |
>= |
大于等于 | a >= b |
如果 a 大于等于 b ,返回 1 ;否则返回 0 |
<= |
小于等于 | a <= b |
如果 a 小于等于 b ,返回 1 ;否则返回 0 |
3. 逻辑运算符
1 |
|
逻辑运算符用于布尔运算,常用于条件语句中的复杂判断。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
&& |
逻辑与 | a && b |
如果 a 和 b 都为真,返回 1 ;否则返回 0 |
|| | 逻辑或 | a || b | 如果 a 或 b 任一个为真,返回 1 ;否则返回 0 |
! |
逻辑非 | !a |
如果 a 为假,返回 1 ;否则返回 0 |
4. 位运算符
位运算符用于位级操作,操作数被视为位模式而非数值。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
& |
按位与 | a & b |
a 和 b 按位与 |
| | 按位或 | a | b | a 和 b 按位或 |
^ |
按位异或 | a ^ b |
a 和 b 按位异或 |
~ |
按位取反 | ~a |
a 的按位取反 |
<< |
左移 | a << 2 |
a 左移 2 位 |
>> |
右移 | a >> 2 |
a 右移 2 位 |
5. 赋值运算符
赋值运算符用于为变量赋值,通常可以结合算术运算符进行简化操作。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
= |
赋值 | a = b |
将 b 的值赋给 a |
+= |
加后赋值 | a += b |
a = a + b |
-= |
减后赋值 | a -= b |
a = a - b |
*= |
乘后赋值 | a *= b |
a = a * b |
/= |
除后赋值 | a /= b |
a = a / b |
%= |
取模后赋值 | a %= b |
a = a % b |
<<= |
左移后赋值 | a <<= 2 |
a = a << 2 |
>>= |
右移后赋值 | a >>= 2 |
a = a >> 2 |
&= |
按位与后赋值 | a &= b |
a = a & b |
^= |
按位异或后赋值 | a ^= b |
a = a ^ b |
|= | 按位或后赋值 | a |= b | a = a | b |
6. 条件运算符(三元运算符)
条件运算符用于根据条件的真假执行不同的表达式。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
? : |
条件表达式(类似 if-else) | a ? b : c |
如果 a 为真,执行 b ,否则执行 c |
7. 其他运算符
1 |
|
除了上述常用的运算符,还有一些其他的运算符,包括取地址、取值、大小、逗号等。
运算符 | 描述 | 示例 | 结果 |
---|---|---|---|
& |
取地址 | &a |
返回变量 a 的地址 |
* |
指针解引用 | *p |
返回指针 p 指向的值 |
sizeof |
计算数据类型大小 | sizeof(a) |
返回 a 的字节大小 |
, |
逗号表达式 | a = (x++, y++) |
先执行 x++ ,再执行 y++ |
-> |
结构体指针成员访问 | p->member |
访问指针 p 指向的结构体的成员 |
. |
结构体成员访问 | s.member |
访问结构体 s 的成员 |
7.运算符优先级
算数 > 关系 > 逻辑 :表格如下
C语言运算符优先级表
优先级最高符号 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
---|---|---|---|---|
1 | () | 括号 | 表达式 | 左结合 |
[] | 数组下标 | 表达式 | 左结合 | |
-> | 取结构体成员(指针) | 表达式 | 左结合 | |
. | 取结构体成员(非指针) | 表达式 | 左结合 | |
sizeof | 返回数据类型大小 | 表达式 | 左结合 | |
2 | ! | 逻辑非 | 表达式 | 右结合 |
~ | 位取反 | 表达式 | 右结合 | |
++ | 自增 | 表达式 | 右结合 | |
-- | 自减 | 表达式 | 右结合 | |
- | 负号 | 表达式 | 右结合 | |
* | 指针 | 表达式 | 右结合 | |
& | 取地址 | 表达式 | 右结合 | |
3 | * | 乘 | 表达式 | 左结合 |
/ | 除 | 表达式 | 左结合 | |
% | 取余 | 表达式 | 左结合 | |
4 | + | 加 | 表达式 | 左结合 |
- | 减 | 表达式 | 左结合 | |
5 | << | 左移 | 表达式 | 左结合 |
>> | 右移 | 表达式 | 左结合 | |
6 | < | 小于 | 表达式 | 左结合 |
<= | 小于等于 | 表达式 | 左结合 | |
> | 大于 | 表达式 | 左结合 | |
>= | 大于等于 | 表达式 | 左结合 | |
7 | == | 等于 | 表达式 | 左结合 |
!= | 不等 | 表达式 | 左结合 | |
8 | & | 按位与 | 表达式 | 左结合 |
9 | ^ | 按位异或 | 表达式 | 左结合 |
10 | | | 按位或 | 表达式 | 左结合 |
11 | && | 逻辑与 | 表达式 | 左结合 |
12 | || | 逻辑或 | 表达式 | 左结合 |
13 | ? : | 条件运算符 | 表达式 | 右结合 |
14 | = | 赋值 | 表达式 | 右结合 |
+= | 加赋值 | 表达式 | 右结合 | |
-= | 减赋值 | 表达式 | 右结合 | |
*= | 乘赋值 | 表达式 | 右结合 | |
/= | 除赋值 | 表达式 | 右结合 | |
%= | 取余赋值 | 表达式 | 右结合 | |
<<= | 左移赋值 | 表达式 | 右结合 | |
>>= | 右移赋值 | 表达式 | 右结合 | |
&= | 按位与赋值 | 表达式 | 右结合 | |
^= | 按位异或赋值 | 表达式 | 右结合 | |
|= | 按位或赋值 | 表达式 | 右结合 | |
15 | , | 逗号 | 表达式 | 左结合 |
考研复试可能会用
逻辑语句
逻辑语句概述
注意 逻辑语句后一般不加分号(;)
1 |
|
C 语言中的逻辑语句主要包括逻辑运算符和条件语句。逻辑语句用于控制程序的执行流程,常用的逻辑语句有 if
、else if
、else
、switch
、while
、for
、do...while
等。
1. 逻辑运算符
逻辑运算符用于连接条件表达式或进行条件判断。C 语言中的逻辑运算符如下表所示:
运算符 | 名称 | 用法 | 结果 |
---|---|---|---|
&& |
逻辑与(AND) | expr1 && expr2 |
若 expr1 和 expr2 均为真,结果为真,否则为假 |
| | 逻辑或(OR) | expr1 逻辑或 expr2 |
若 expr1 和 expr2 任一真,结果为真 |
! |
逻辑非(NOT) | !expr |
若 expr 为真,结果为假,反之亦然 |
2. 条件语句
C 语言中的条件语句用于根据不同的条件执行不同的代码块。以下是常见的条件语句:
语句 | 用法 | 解释 |
---|---|---|
if |
if (condition) { /* code */ } |
当 condition 为真时,执行 { /* code */ } |
if...else |
if (condition) { /* code1 */ } else { /* code2 */ } |
如果 condition 为真,执行 code1 ,否则执行 code2 |
else if |
if (condition1) { /* code1 */ } else if (condition2) { /* code2 */ } else { /* code3 */ } |
多条件判断,第一个为真的条件执行相应的代码块 |
switch |
switch (expression) { case val1: /* code */ break; case val2: /* code */ break; default: /* code */ } |
根据 expression 的值选择执行相应的 case 代码块 |
3. 循环语句
C 语言中的循环语句用于重复执行某一代码块,直到满足指定的条件。
语句 | 用法 | 解释 |
---|---|---|
while |
while (condition) { /* code */ } |
当 condition 为真时,重复执行 { /* code */ } |
do...while |
do { /* code */ } while (condition); |
先执行一次代码块,再根据 condition 判断是否继续 |
for |
for (init; condition; increment) { /* code */ } |
常用循环,按照初始化、条件判断、增量控制的顺序执行 |
4. 三元运算符
三元运算符是简化 if...else
语句的方式,语法如下:
运算符 | 用法 | 解释 |
---|---|---|
?: |
condition ? expr1 : expr2 |
当 condition 为真时,返回 expr1 ,否则返回 expr2 |
5.continue和break
语句 | 用法 | 解释 |
---|---|---|
continue |
continue; |
当循环语句中出现 continue 时,跳过本次循环,执行下一次循环 |
break |
break; |
当循环语句中出现 break 时,打断循环,执行后续语句 |
数组
数组类型 | 用法示例 | 访问方式 | 特点 |
---|---|---|---|
一维数组 | int arr[5]; |
arr[i] |
固定大小,元素在内存中连续存储。 |
二维数组 | int arr[3][4]; |
arr[i][j] |
类似矩阵,元素按行优先存储。 |
多维数组 | int arr[2][3][4]; |
arr[i][j][k] |
用于复杂的多维数据存储。 |
字符数组 | char str[] = "Hello"; |
str[i] |
以 '\0' 结尾,表示字符串。 |
动态数组 | int *arr = (int *)malloc(5 * sizeof(int)); |
arr[i] |
动态分配内存,大小可变。 |
参数传递 | void func(int arr[], int size) |
arr[i] |
传递指针,需要传递数组大小。 |
一维数组
1 |
|
主要 数组索引从0开始,因此大小为10的数组实际索引为0到9
关于数组初始化 :
通常可在数组后添加一个新的变量来动态的记录数组长度,常用的以为数组长度算法为int length_a = sizeof(a) / sizeof(int);
关于数组越界的问题 :
在访问数组时,如果使用的索引超出了数组的有效范围,可能会导致不可预知的行为或程序崩溃。从内存层面上,溢出的数组值会和该数组相邻的变量产生冲突,使得该变量获得错误的值,Visual Studio 2022会自动检测数组下标溢出问题,并阻止编译,但其他编译器仍可能出现问题
多维数组
1 |
|
多维数组的内存结构
二维数组在内存中是按行连续存储的。例如,matrix[2][3]
在内存中的存储顺序为:matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0], matrix[1][1], matrix[1][2]
。
数组传递
1 |
|
数组传递是按指针传递的,你传递的是数组首元素的地址,而不是整个数组。数组名退化为指针
数组的长度信息不会自动传递,数组长度信息丢失,需要手动传递长度。上述代码提供了一个可行的长度传递逻辑
指针传递使得函数可以修改原数组的值,因为指针指向的是相同的内存地址。
字符数组
1 |
|
关于字符数组初始化
字符数组是用于存储字符的数组,通常用于存储和处理字符串。在C语言中,字符串是以空字符 '\0'
结尾的字符数组,在对字符数组进行操作是要尤为注意索引问题
字符串操作函数str系列
该系列操作函数需调用<string.h>
在 C 语言中,string.h
头文件中提供了一些常用的字符串操作函数,包括 strlen
、strcpy
、strcat
和 strcmp
。这些函数专门用于处理以 '\0'
结尾的字符串
其中strcpy
、strcat
由于其安全性的不足而被弃用,现用更安全的strcpy_s
和strcat_s
,他们要求提供dest_size
: 目标字符串的大小(总字节数,必须包含足够的空间来容纳源字符串和终止符 \0
)来防止字符串溢出组中
dest_size
必须包含现有字符串、源字符串以及终止符 \0
。
如果目标缓冲区不够大,函数将不会追加字符串并返回错误。
如果目标或源字符串指针为 NULL
,函数也会返回错误。
1 |
|
函数 | 功能 | 返回值 | 用法示例 | 注意事项 |
---|---|---|---|---|
strlen |
计算字符串长度 | 返回字符串长度,不含 \0 |
size_t len = strlen(str); |
只计算 \0 之前的字符,不包括 \0 ,且传入字符串必须以 \0 结尾 |
strcpy_s |
安全地将源字符串复制到目标字符串 | 返回目标字符串指针 | strcpy(dest,sizeof(dest), src); |
目标缓冲区必须足够大以容纳源字符串和 \0 ,否则失败 |
strcat_s |
安全地将源字符串追加到目标字符串后 | 返回目标字符串指针 | strcat(dest,sizeof(dest), src); |
目标缓冲区必须包含现有字符串、源字符串和 \0 ,否则失败 |
strcmp |
比较两个字符串 | 0:相等,正数:大于,负数:小于 | int cmp = strcmp(str1, str2); |
按字典顺序比较,区分大小写,比较到第一个不同的字符即停止 |
指针
标准代码架构
1 | ooo |
标准代码架构
1 | ooo |
标准代码架构
1 | ooo |
函数
标准代码架构
1 | ooo |
标准代码架构
1 | ooo |
标准代码架构
1 | ooo |
C++引用
标准代码架构
1 | ooo |
- Title: C_Note
- Author: Slience_Displace
- Created at: 2024-10-14 00:00:00
- Updated at: 2024-10-21 21:25:53
- Link: https://mikumikudaifans.github.io/Displace.github.io/2024/10/14/C_Note/
- License: This work is licensed under CC BY-NC-SA 4.0.