自己整理的C语言基础学习笔记,参考了挺多资料的,适合梳理知识框架,进而攻克各个知识点。
这是第一篇,初窥门径:认识C语言。
什么是C语言
C语言是一门计算机语言——>计算机语言是什么?——>人和计算机交流的语言(C、C 、Python….)
语言的发展
二进制语言——>硬件(0、1) !!!太复杂需要查手册
汇编语言——>整理合并助记 !!!同样复杂
B语言——>C语言,C … ——>高级语言
(低级到搞基,哦不,低级到高级)
C语言的发展
C语言——>不成熟——>成熟——>流行
标准的制定,C89/C90——C99——C11
编译器:MSVS、GCC
C语言的优势
- 效率高 C语言是编译型语言,目前流行的还有解释型语言,像python,JavaScript等。 编译型语言就像做好了一桌子菜,就开吃。 解释型语言就像吃火锅,边做边吃。
- 灵活度高 可以直接操作硬件,语法简单,约束性少造就C的灵活性。
- 可移植性高 C生万物,C的可移植性很高。
第一个C语言程序
- 新建项目——>空项目/控制台 ——>新建源文件,后缀名.cpp改成.c
- 敲代码。
#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)
、下划线_
组成的字符串,并且第一个字符必须是字母或下划线。在使用标识符时还有注意以下几点:
- 标识符的长度最好不要超过8位,因为在某些版本的C中规定标识符前8位有效,当两个标识符前8位相同时,则被认为是同一个标识符。
- 标识符是严格区分大小写的。
- 标识符最好选择有意义的英文单词组成做到”见名知意”,不要使用中文。
- 标识符不能是C语言的关键字(语言系统之前定好的标识符,比如int,char等等,后面学到就懂了)
常量和变量
常量:固定不变的量
- 字面常量
- 整型常量
- 实型常量
- 字符常量
- 字符串常量
- 符号常量
- const修饰的常变量
- #define定义的标识符常量
- enum枚举常量
变量:变化的量
变量运用
代码语言:javascript复制#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 关键字,它的作用域就变成了当前文件,在其它文件中就无效了。
内部定义/外部定义:全局变量的作用域是整个工程。
生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期。
数据类型
代码语言:javascript复制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 |
字符串
代码语言:javascript复制由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。 注:字符串的结束标志是一个 的转义字符。在计算字符串长度的时候 是结束标志,不算作字符串内容。
#include <stdio.h>
int main (void)
{
char arr1[]="abc";
char arr2[]={'a','b','c'};
printf("%sn",arr1[]);
printf("%sn",arr2[]);
return 0;
}
//字符串末尾默认有 ,字符串结束标志,程序遇到 停止。
//arr1[]比arr2[]多
//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:test32test.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函数,但是这是微软的编译器特有的,如果移植到别的编译器里,那么平台的通用性将会变差。
在文件前面的上(每次都加,麻烦)
代码语言:javascript复制#define _CRT_SECURE_NO_WARNINGS 1
这样可以停止报错,但是每次创建文件都要加也是很烦。(当然还有的方法是修改文件属性里的宏定义,一样的道理)
通过文件长期修改(一劳永逸,推荐)
建议使用这种解决方案。每次创建文件时,系统自动添加方法二的代码。 ``D:Visual Studio 2019Common7IDEVCvcprojectitems`
需要注意的是不同版本这个文件的位置有所不同,我们可以直接搜索目标文件newc file.cpp
用其他编辑器打开(通常用Notepad )
加入 ``#define _CRT_SECURE_NO_WARNINGS 1`后保存。