一. 前言
1. C语言概述
1.1 C语言介绍
C语言是计算机编程语言的一种, 编程语言则用于人与机器之间的交流, C语言则是通过编译器翻译成机器语言, 计算机可以将程序转换成二进制指令,并由CPU执行,CPU会按照指令的顺序,依次执行每个命令,简单来说只需要记住,C语言就是编译语言。
1.2 C语言特点
- 简洁: C语言的语法简单,语句清晰明了,使得程序更容易阅读和理解
- 高效: C语言的执行效率高,可以用于开发需要高性能的应用程序
- 可移植: C语言可以在不同的硬件平台和操作系统上运行,具有较高的可移植性
- 模块化: C语言支持函数和结构体等模块化编程方式, 使得程序的复杂性得到有效控制
- 标准化: C语言的语法和标准库已经被ISO和ANSI标准化,具有广泛的应用和兼容性
1.3 C语言应用领域
- 系统软件: 操作系统, 编译器, 数据库等
- 嵌入式系统: 智能家电, 只能穿戴设备, 智能汽车等
- 网络设备: 路由器, 交换机, 防火墙等
- 游戏开发: 电脑游戏, 手机游戏等
二. 基础语法
1. 数据类型
数据类型: 基本类型, 构造函数, 指针类型
其中:
基本类型: 整型(int, short, long)
字符型(char)
实型(浮点型)(float, double)
构造类型: 数组类型
构造类型 struct
联合类型 union
枚举类型 enum
指针类型: (char *, int *, int ** 等)
1.1 变量
变量定义:
就是存储数据的空间,类型不同,空间不同。
变量的命名:
数字,字母,下划线构成,但是不可以使用数字开头。
1.2 命名规则和规范
标识符是用户编程时使用的名字, 用于给变量、 函数、 类等命名
-
命名规则
-
规则:规则是一定要遵循,不遵循就报错
-
由数字, 字母, 下划线_组成
-
不能使用数字开头
-
不能使用关键字
-
严格区分大小写
-
-
命名规范虽然可以不去严格遵守, 但是建议,见名知意,使用大驼峰或者小驼峰来命名。
1.3 char类型
char的本质就是一个1字节大小的整型(单个存储字符), 一个字符对应一个ASCII编码数字
每个字符变量都是由8个bit位构成的,在内存中就是1个字节
#include <stdio.h>
int main()
{
/*
1字节 = 8位 1B = 8b
*/
char c = 'a';
printf("%c\n", c);
// %d 打印的是对应的ASCII码:97
printf("%d\n", c);
// A:65 a:97
char a = 'a';
printf("%d\n", a); // 97
printf("%d\n", a - 32); // 65
printf("%c\n", a - 32); // A
return 0;
}
1.4 bool类型
早期C语言没有布尔类型数据,以0代表逻辑假,1代表逻辑真
C99标准定义了新的关键字_Bool,提供了布尔类型,或者也可以使用stdbool.h中的bool
// 使用布尔时需要导入
#include <stdbool.h>
#include <stdio.h>
int main() {
// 布尔的本质 0 1
int is_sale = true;
int is_open = false;
printf("%d\n",is_sale); //1:true
printf("%d\n",is_open); //0:false
return 0;
}
1.5 数据类型长度 sizeof
- bit(比特): 一个二进制代表一位, 一个位只能表示0或者1两种状态
- bite(字节): 一个字节为8个二进制,称为8位, 计算机中存储嗯嗯最小单位是字节
- sizeof: 查看数据的长度,长度在不同平台上看到不一样
#include <stdio.h>
int main()
{
int a = 1;
printf("%d\n", sizeof(a)); // 4
short b = 2;
printf("%d\n", sizeof(b)); // 2
printf("%d\n", sizeof(long)); // 4
printf("%d\n", sizeof(long long)); // 8
printf("%d\n", sizeof(float)); // 4
printf("%d\n", sizeof(long double)); // 16
return 0;
}
1.6 可移植的类型
C语言在可移植类型 stdint.h 和 inttype.h中规定了精确的宽度整数类型,以确保C语言的类型在各系统内功能相同
#include <stdio.h>
#include <inttypes.h>
int main() {
// 可移植类型,保障各个平台的数据类型相同
// 八位整型
int8_t a = 127;
printf("%d\n",a);
printf("int8_t = %d\n",sizeof(a));
// 十六位整型
int16_t b = 123;
printf("%d\n",b);
printf("int16_t = %d\n",sizeof(b));
// undigned无符号, 没有符号位, 数值为正数
uint8_t m = 290;
printf("%d\n",m); //34因为超出范围
return 0;
}
1.7 常量 (define/const)
与变量不同, 常量的值在程序运行时不会改变
#include <stdio.h>
#define Pi 3.1415
// 使用define或者const定义常量
int main() {
// 常量: 不可更改的数据
const int num = 8;
//num = 10; 不对,不可改变
const float pi = 3.14;
printf("%f\n",pi);
printf("%f\n",Pi);
return 0;
}
三. 数值表示
1. 进制
进制 | 描述 |
---|---|
十进制 | 以正常数字1-9开头,如15 |
八进制 | 以数字0开头,如017 |
十六进制 | 以0x或0X开头,如0xf |
二进制 | 以0b或0B开头,如0b1111 |
1.1 二进制
- 二进制是计算技术中广泛采用的一种数制。二进制数据是用0和1两个数码来表示的数
-
- 它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”
- 当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的
- 十进制转化二进制的方法:
-
- 用十进制数除以2,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果
口诀:除二取余,倒序排列法
1.2 八进制
- 八进制,Octal,缩写OCT或O,一种以8为基数的计数法,采用0,1,2,3,4,5,6,7八个数字,逢八进1
-
- 一些编程语言中常常以数字0开始表明该数字是八进制
- 八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中
- 八进制和二进制互转
- 十进制转化八进制的方法:
-
- 用十进制数除以8,分别取余数和商数,商数为0的时候,将余数倒着数就是转化后的结果
1.3 十六进制
- 十六进制(英文名称:Hexadecimal),同我们日常生活中的表示法不一样,它由0-9,A-F组成,字母不区分大小写
-
- 与10进制的对应关系是:0-9对应0-9,A-F(或a-f)对应10-15
- 十六进制的数和二进制数可以按位对应(十六进制一位对应二进制四位),因此常应用在计算机语言中
- 十六进制和二进制互转:
2. 进制转换
十进制 | 二进制 | 八进制 | 十六进制 |
0 | 0 | 0 | 0 |
1 | 1 | 1 | 1 |
2 | 10 | 2 | 2 |
3 | 11 | 3 | 3 |
4 | 100 | 4 | 4 |
5 | 101 | 5 | 5 |
6 | 110 | 6 | 6 |
7 | 111 | 7 | 7 |
8 | 1000 | 10 | 8 |
9 | 1001 | 11 | 9 |
10 | 1010 | 12 | A |
11 | 1011 | 13 | B |
12 | 1100 | 14 | C |
13 | 1101 | 15 | D |
14 | 1110 | 16 | E |
15 | 1111 | 17 | F |
16 | 10000 | 20 | 10 |
3. 数值存储方式
-
在计算机系统中,数值一律用补码来存储
(1+(-1) = 0)
1. 原码: 本身数字的二进制
负数的二进制就是正数的二进制第一位变成1
1:0000 0001 -1:1000 0001
(0000 0001 + 1000 0001 = 1000 0010 [-2(结果不对)])
十进制 原码 5 0000 0101 10 0000 1010 0 0000 0000 -1 1000 0001 -5 1000 0101 2. 反码: 正数的反码就是原码本身
负数: 负数的反码:符号位不变(第一位还是1),后面的取反(1变0,0变1)
1:0000 0001 -1:1111 1110
(0000 0001 + 1111 1110 = 1111 1111)
(此时1111 1111是反码,把它转成原码就是1000 0000 [-0(存在正负0的问题)])
3. 补码: 正数的补码就是原码本身
负数: 负数的补码:反码的基础上+1
1:0000 0001 -1:1111 1111
(0000 0001 + 1111 1111 = 0000 0000(最大1111 1111,再加1,就重置了,为0))
四. 程序的输入和输出
1. 输出 printf
#include <stdio.h>
int main()
{
// 输出
int i = 12;
long l = 23;
short s = 44;
char c = 'a';
char *cc = "123abc";
float f = 12.12;
double d = 23.2;
unsigned int ui = 20;
printf("%d\n", i);
printf("%d\n", l);
printf("%d\n", s);
printf("%c\n", c);
printf("%s\n", cc);
printf("%f\n", f);
printf("%lf\n", d);
// 无符号数据
printf("%u\n", ui);
// 八进制和十六进制, 可以加上前缀# 自动输出八进制和十六进制0或者0x
// 八进制: %#o, 十六进制: %#x
printf("%#o\n", 120); // 八进制 (0170)
printf("%#x\n", 120); // 十六进制(0x78)
return 0;
}
2. 输入 scanf
#include <stdio.h>
int main()
{
/**
* 输入: scanf("格式化字符串",&变量1,&变量2...)
* 输入年龄并打印
* 数据是给定变量的地址,而不是给变量
*/
int age;
printf("%s", "请输入年龄:");
scanf("%d", &age);
printf("您的年龄是:%d\n", age);
return 0;
}
3. 输入输出案例
#include <stdio.h>
int main()
{
// 1. 定义常量pi
const float pi = 3.14;
// 2. 定义变量半径
int r;
// 3. 输入半径
printf("请输入半径:");
scanf("%d", &r);
// 4. 求圆的周长和面积
float len = pi * r * 2;
float area = pi * r * r;
printf("周长 = %f, 面积 = %f\n", len, area);
return 0;
}
五. 运算符
运算符就是在各种运算中起到特定作用的符号
1. 算数运算符
运算符 | 术语 | 示例 | 结果 |
+ | 加 | 10 + 5 | 15 |
- | 减 | 10 - 5 | 5 |
* | 乘 | 10 * 5 | 50 |
/ | 除 | 10 / 5 | 2 |
% | 取模(取余) | 10 % 3 | 1 |
++ | 前自增 | a=2; b=++a; | a=3; b=3; |
++ | 后自增 | a=2; b=a++; | a=3; b=2; |
-- | 前自减 | a=2; b=--a; | a=1; b=1; |
-- | 后自减 | a=2; b=a--; | a=1; b=2; |
#include <stdio.h>
int main()
{
float f = 5;
int i = 2;
printf("%d\n", f + i);
printf("%f\n", f + i);
/*
在不同类型之间进行运算时:
int类型会自动被转成float类型,然后与f进行运算,所以结果为float
当在打印时,试图计算的是指向内存地址的指针,用于打印整数,
而在不同类型之间进行计算,没有传递一个合法的内存地址给printf,而是传递一个整数值
*/
int a = 3;
int b = 2;
printf("%d\n", a + b);
// 前++ 先加,再运算
int c = 0;
int d = ++c;
printf("%d\n", d); // 1
printf("%d\n", c); // 1
// 后++ 先运算,再加
int e = 1;
int g = e++;
printf("%d\n", g); // 1
printf("%d\n", e); // 2
return 0;
}
2. 逻辑运算符
运算符 | 术语 | 示例 | 结果 |
! | 非 | !a | 如果a为假,则!a为真; 如果a为真,则!a为假。 |
&& | 与 | a && b | 如果a和b都为真,则结果为真,否则为假。 |
|| | 或 | a || b | 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。 |
#include <stdio.h>
int main() {
// &&(与),可以理解为并且
// 案例:请判断班长和他女朋友是否符合法定结婚年龄
int boy = 25;
int girl = 21;
int result = boy >= 22 && girl >= 20;
printf("%d\n", result);
// ||(或),可以理解为或者
// 案例:班长女朋友玩原神没有原石了,请帮班长判断是否有足够的钱
double wx_money = 100;
double alipay_money = 300;
result = wx_money >= 398 || alipay_money >= 398 || wx_money+alipay_money >= 398;
printf("%d\n", result);
// !(非),可以理解为不是
printf("%d\n", !0);
printf("%d\n", !!1);
// 短路规则
// && 左边为假,右边不执行
0 && printf("我是右边\n");
// || 左边为真,右边不执行
1 || printf("我是右边\n");
return 0;
}
3. 赋值运算符
运算符 | 术语 | 示例 | 结果 |
= | 赋值 | a=2; b=3; | a=2; b=3; |
+= | 加等于 | a=0; a+=2; 等同于 a = a + 2; | a=2; |
-= | 减等于 | a=5; a-=3; 等同于 a = a - 3; | a=2; |
*= | 乘等于 | a=2; a*=2; 等同于 a = a * 2; | a=4; |
/= | 除等于 | a=4; a/=2; 等同于 a = a / 2; | a=2; |
%= | 模等于 | a=3; a%=2; 等同于 a = a % 2; | a=1; |
4.比较运算符
C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。
运算符 | 术语 | 示例 | 结果 |
== | 相等于 | 4 == 3 | 0 |
!= | 不等于 | 4 != 3 | 1 |
< | 小于 | 4 < 3 | 0 |
> | 大于 | 4 > 3 | 1 |
<= | 小于等于 | 4 <= 3 | 0 |
>= | 大于等于 | 4 >= 1 | 1 |
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
printf("%d\n", a == b);
printf("%d\n", a != b);
printf("%d\n", a > b);
printf("%d\n", a < b);
printf("%d\n", a >= b);
printf("%d\n", a <= b);
return 0;
}