自己整理的C语言基础学习笔记,参考了挺多资料的,适合梳理知识框架,进而攻克各个知识点。

这是第一篇,初窥门径:认识C语言。


什么是C语言

C语言是一门计算机语言——>计算机语言是什么?——>人和计算机交流的语言(C、C++、Python….)


语言的发展

二进制语言——>硬件(0、1) !!!太复杂需要查手册

汇编语言——>整理合并助记 !!!同样复杂

B语言——>C语言,C++ … ——>高级语言

(低级到搞基,哦不,低级到高级)


C语言的发展

C语言——>不成熟——>成熟——>流行

标准的制定,C89/C90——C99——C11

编译器:MSVS、GCC


C语言的优势

  1. 效率高

    C语言是编译型语言,目前流行的还有解释型语言,像python,JavaScript等。

    编译型语言就像做好了一桌子菜,就开吃。

    解释型语言就像吃火锅,边做边吃。

  2. 灵活度高

    可以直接操作硬件,语法简单,约束性少造就C的灵活性。

  3. 可移植性高

    C生万物,C的可移植性很高。


第一个C语言程序

  1. 新建项目——>空项目/控制台 ——>新建源文件,后缀名.cpp改成.c
  2. 敲代码。
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>				//#是一个引用的标志,include是英语引用的意思
//<stdio.h>是库函数中的一个函数
//格式化输入输出函数,standard+input+output缩写而成.h是头文件后缀
int main(void) //主函数
{
printf("Hello World!\n"); //printf();函数是格式化打印的意思,print是打印的意思
//printf中的f有的地方说是format格式化的意思,也有的地方说是function函数的意思
//\n是转义字符,表示换行
return 0; //return 0表示函数返回值为0
}

标识符

  C语言规定,标识符可以是字母(A~Z,a~z)、数字(0~9)、下划线_组成的字符串,并且第一个字符必须是字母或下划线。在使用标识符时还有注意以下几点:

  1. 标识符的长度最好不要超过8位,因为在某些版本的C中规定标识符前8位有效,当两个标识符前8位相同时,则被认为是同一个标识符。
  2. 标识符是严格区分大小写的。
  3. 标识符最好选择有意义的英文单词组成做到”见名知意”,不要使用中文。
  4. 标识符不能是C语言的关键字(语言系统之前定好的标识符,比如int,char等等,后面学到就懂了)

常量和变量

常量:固定不变的量

  1. 字面常量
    • 整型常量
    • 实型常量
    • 字符常量
    • 字符串常量
    • 符号常量
  2. const修饰的常变量
  3. #define定义的标识符常量
  4. enum枚举常量

变量:变化的量

  • 变量运用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>

    int main(void)
    {
    int a, b;//变量定义,数据类型+变量名;//int a=b=c=0;这样定义不合法。

    scanf("%d%d",&a,&b);//scanf格式化输入函数,取地址

    return 0;
    }
  • 注意:当局部变量和全局变量重名时,局部变量优先使用。

  • 变量的作用域

    作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的
    而限定这个名字的可用性的代码范围就是这个名字的作用域。

    局部变量:在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了。

    全局变量:全局变量的默认作用域是整个程序,也就是所有的代码文件,包括源文件(.c文件)和头文件(.h文件)。如果给全局变量加上 static 关键字,它的作用域就变成了当前文件,在其它文件中就无效了。

    内部定义/外部定义:全局变量的作用域是整个工程。

  • 生命周期

    变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段

    1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
    2. 全局变量的生命周期是:整个程序的生命周期。

数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
graph TD
A(数据类型)-->B1(基本类型)
A-->B2(指针类型)
A-->B3(构造类型)
A-->B4(空类型)
B1-->C1(整数类型)
B1-->C2(浮点数类型)
B1-->C3(字符类型)
B1-->C4(布尔类型)
B1-->C5(枚举类型)
B3-->D1(数组类型)
B3-->D2(结构类型)
B3-->D3(联合类型)

浮点型,整型,字符型,字符串型…

%f,%lf, %d , %c, %s, ……..

因为现实生活中的数据存在不同的大小之分,所以存在这么多数据类型,每种数据类型所占内存大小不同。


sizeof运算符

用sizeof运算符计算不同的类型所占的内存大小。

sizeof的三种使用方式

  • sizeof(类型)、sizeof(对象)、sizeof 对象
数据类型 所占内存(32位/64位) 取值范围
char 1个字节 -128~127
unsigned char 1个字节 0~255
char*(指针变量) 4个字节/(8个字节) -2147483648~-2147483647
short 2个字节 -32768~32767
unsigned short 2个字节 0~65535
int 4个字节 -2147483648~-2147483647
unsigned int 4个字节 0~4294967295
long 4个字节/(8个字节) -2147483648~-2147483647/
unsigned long 4个字节/(8个字节) 0~4294967295
long long 8个字节 -9223372036854775808~9223372036854775807
unsigned long long 8个字节 0~18446744073709551615
float 4个字节 -2128 ~ -2128
double 8个字节 -21024 ~21024

字符

ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 ! 65 A 97 a
2 STX 34 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 S 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 / 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 `
31 US 63 ? 95 _ 127 DEL

字符串

由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。

注:字符串的结束标志是一个\0的转义字符。在计算字符串长度的时候\0是结束标志,不算作字符串内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main (void)
{
char arr1[]="abc";
char arr2[]={'a','b','c'};

printf("%s\n",arr1[]);
printf("%s\n",arr2[]);

return 0;
}
//字符串末尾默认有\0,字符串结束标志,程序遇到\0停止。
//arr1[]比arr2[]多\0
//arr1[]长度为3;arr2[]长度为随机值
//stren计算长度,需要引用头文件string

转义字符

转义字符 含义 ASCII码(16/10进制)
\o 空字符*(NULL)* 00H/0
\n 换行符*(LF)* 0AH/10
\r 回车符*(CR)* 0DH/13
\t 水平制表符*(HT)* 09H/9
\v 垂直制表*(VT)* 0B/11
\a 响铃*(BEL)* 07/7
\b 退格符*(BS)* 08H/8
\f 换页符*(FF)* 0CH/12
\’ 单引号 27H/39
\” 双引号 22H/34
*\* 反斜杠 5CH/92
? 问号字符 3F/63
\ddd 任意字符 三位八进制
\xhh 任意字符 二位十六进制
  • 特殊

    ??+ —— 三字母符号 ??

    把斜杠转义掉,\\表示一个斜杠,打印电脑存盘的路径

  • strlen(“c:\test\32\test.c”)输出结果

    \t表示一个字符,转义字符

    \32(\ddd)表示一个八进制的=3*8+2=26

    \xddd十六进制数字


运算符

算数运算符

运算符 描述 实例
+ 两个数相加 A+B 将得到 23
- 一个数减另一个数 A-B 将得到 13
***** 两个数相乘 A*B 将得到 90
/ 分子除以分母 A/B 将得到 3.6
% 余数运算符,整除后的余数 B%A 将得到 3
++ 自增运算符,整数值增加 1 A++ 将得到 19
自减运算符,整数值减少 1 A– 将得到 17

赋值运算符

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 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

优先级

  基本的优先级需要记住:指针最优,单目运算优于双目运算。如正负号。先乘除(模),后加减。先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7等价于 (1 << (3 + 2))&7.逻辑运算最后计算。

  C语言常用运算符的优先级口诀是:“单算关逻条赋逗”;如果加入位运算符,完整口诀是:“单算移关与,异或逻条赋”。

  • “单”表示单目运算符:逻辑非(!),按位取反(~),自增(++),自减(–),取地址(&),取值(*);
  • “算”表示算术运算符:乘、除和求余(*,/,%)级别高于加减(+,-);
  • “移”表示按位左移(<<)和位右移(>>);
  • “关”表示关系运算符:大小关系(>,>=,<,<=)级别高于相等不相等关系(==,!=);
  • “与”表示按位与(&);
  • “异”表示按位异或(^);
  • “或”表示按位或(|);
  • “逻”表示逻辑运算符:逻辑与(&&)级别高于逻辑或(||);
  • “条”表示条件运算符(? :);
  • “赋”表示赋值运算符(=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=, |=,!=);
  • 另,逗号运算符(,) 级别最低,口诀中没有表述,需另加记忆..
优先级 运算符 名称或含义 使用形式 结合方向 说明
1 后置++ 后置自增运算符 变量名++ 左到右
后置– 后置自减运算符 变量名–
[ ] 数组下标 数组名[整型表达式]
( ) 圆括号 (表达式)/函数名(形参表)
. 成员选择(对象) 对象.成员名
-> 成员选择(指针) 对象指针->成员名
2 - 负号运算符 -表达式 右到左 单目运算符
(类型) 强制类型转换 (数据类型)表达式
前置++ 前置自增运算符 ++变量名 单目运算符
前置– 前置自减运算符 –变量名 单目运算符
* 取值运算符 *指针表达式 单目运算符
& 取地址运算符 &左值表达式 单目运算符
! 逻辑非运算符 !表达式 单目运算符
~ 按位取反运算符 ~表达式 单目运算符
sizeof 长度运算符 sizeof 表达式/sizeof(类型)
3 / 表达式/表达式 左到右 双目运算符
* 表达式*表达式 双目运算符
% 余数(取模) 整型表达式%整型表达式 双目运算符
4 + 表达式+表达式 左到右 双目运算符
- 表达式-表达式 双目运算符
5 << 左移 表达式<<表达式 左到右 双目运算符
>> 右移 表达式>>表达式 双目运算符
6 > 大于 表达式>表达式 左到右 双目运算符
>= 大于等于 表达式>=表达式 双目运算符
< 小于 表达式<表达式 双目运算符
<= 小于等于 表达式<=表达式 双目运算符
7 == 等于 表达式==表达式 左到右 双目运算符
!= 不等于 表达式!= 表达式 双目运算符
8 & 按位与 整型表达式&整型表达式 左到右 双目运算符
9 ^ 按位异或 整型表达式^整型表达式 左到右 双目运算符
10 | 按位或 整型表达式|整型表达式 左到右 双目运算符
11 && 逻辑与 表达式&&表达式 左到右 双目运算符
12 || 逻辑或 表达式||表达式 左到右 双目运算符
13 ?: 条件运算符 表达式1? 表达式2: 表达式3 右到左 三目运算符
14 = 赋值运算符 变量=表达式 右到左
/= 除后赋值 变量/=表达式
*= 乘后赋值 变量*=表达式
%= 取模后赋值 变量%=表达式
+= 加后赋值 变量+=表达式
-= 减后赋值 变量-=表达式
<<= 左移后赋值 变量<<=表达式
>>= 右移后赋值 变量>>=表达式
&= 按位与后赋值 变量&=表达式
^= 按位异或后赋值 变量^=表达式
|= 按位或后赋值 变量|=表达式
15 , 逗号运算符 表达式,表达式,… 左到右 从左向右顺序运算

类型转换

  当一个运算符的几个操作数类型不同时会发生什么情况?

  当一个运算符的几个操作数类型不同时,编译器需要将他们转化为相同的数据类型才能运算,通常情况下,编译器会将占用坑位小的数据类型转换成占用坑位大的来运算,这样做是为了确保计算精度。

  除此之外,我们还可以进行强制转换,比如(int)2.0便将浮点型的数据2.0转换成了整型数据2,那么int(2.5)或者int(2.9)等于多少呢?其实结果同样也为2,C语言内部的做法是直接去掉小数,而不是四舍五入。


注释

  注释的意思:我之前听过一个老师说注释是注销解释的的意思,注销指的是让一段代码失效,解释就是解释这段代码的意思。

(也许词典上并没有注销的一层含义,但用在编程上再恰当不过了)

 注释的作用:方便代码的可读性和直观性,代码中有不需要的代码可以直接删除,也可以注释起来,谨防日后需要。

  注释风格:/*.....*/ 一段 //一行


关于vs2019编译器中scanf函数不安全报错信息的解决方案

  刚用vs2019编译器的时候会遇到这样的报错信息 error C4996: ‘scanf’: This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

使用scanf_s函数(不建议)

  编译器建议使用scanf_s函数,但是这是微软的编译器特有的,如果移植到别的编译器里,那么平台的通用性将会变差。

在文件前面的上(每次都加,麻烦)

1
#define _CRT_SECURE_NO_WARNINGS 1

  这样可以停止报错,但是每次创建文件都要加也是很烦。(当然还有的方法是修改文件属性里的宏定义,一样的道理)

通过文件长期修改(一劳永逸,推荐)

   建议使用这种解决方案。每次创建文件时,系统自动添加方法二的代码。
  ``D:\Visual Studio 2019\Common7\IDE\VC\vcprojectitems`

  需要注意的是不同版本这个文件的位置有所不同,我们可以直接搜索目标文件newc++file.cpp

  用其他编辑器打开(通常用Notepad++) 加入 ``#define _CRT_SECURE_NO_WARNINGS 1`后保存。

img