网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
const int num = 10;
num = 20; //error, 不能修改
printf("num = %d\n", num);
}
>
> 🚩 运行结果: 10
>
>
>
💬 #define 定义的标识符常量:
#define MAX 10000 // 不写=,不加分号!
int main()
{
int n = MAX;
printf(“%d\n”, n);
}
>
> 🚩 运行结果:10000
>
>
>
💬 枚举常量:
//性别
enum Sex {
//这种枚举类型的变量的未来可能取值
//枚举常量
MALE = 3, //赋初值
FEMALE,
SECRET
};
int main()
{
enum Sex s = MALE;
printf(“%d\n”, MALE);
// MALE = 3 error 不可修改
printf(“%d\n”, FEMALE);
printf(“%d\n”, SECRET);
return 0;
}
📌 注意事项:
const 只是一个有常属性的变量,本质上仍然为变量!arr[], 数组的大小必须是常量!
int main()
{
const int n = 10; //n是变量,但是又有常属性,所以我们说n是常变量
int arr[n] = {0}; // 仍然不可以,因为n是变量,只是有常属性而已
return 0;
}
💬 #define 定义的可以,宏定义用得最多的地方是在数组中用于指定数组的长度:
#define N 10
int main()
{
int arr[N] = {0};
return 0;
}
📌 注意事项:
枚举常量虽然是不能改变的,但是通过枚举常量创造出来的变量是可以改变的!
enum Color
{
// 枚举常量
RED,
YEELOW,
BULE
};
int main()
{
enum Color c = BULE; //我们创建一个变量c,并将BULE赋给它
c = YEELOW; //这时将YEELOW赋给它,完全没有问题 ✅
BULE = 6; //error!枚举常量是不能改变的 ❌
return 0;
}
### 四、字符串&转义字符&注释
#### 0x00 字符串
📚 定义:
"hello world."
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal)
📚 关于斜杠零:
字符串的结束标志是一个 \0 转义字符。
在计算字符串长度的时候 \0 是结束标志,不算字符串的内容!
💬 下面代码,打印的结果是什么?为什么?
int main()
{
char arr1[] = “abc”; //数组
// “abc” – ‘a’ ‘b’ ‘c’ ‘\0’
// 这里面,‘\0’ 字符串的结束标志
char arr2[] = {‘a’, ‘b’, ‘c’};
char arr3[] = {‘a’, ‘b’, ‘c’, ‘\0’};
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
>
> 🚩 打印结果如下:
>
>
>
![](https://img-blog.csdnimg.cn/20210924133505820.png)
#### 0x01 计算字符串长度
📚 strlen 函数:返回字符串的长度
📜 使用时需引入头文件 <string.h>
![](https://img-blog.csdnimg.cn/20210924133622672.png)
💬 代码演示:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = “abc”;
char arr2[] = {‘a’, ‘b’, ‘c’};
printf(“%d\n”, strlen(arr1));
printf(“%d\n”, strlen(arr2));
return 0;
}
>
> 🚩 运行结果如下: 3 *随机值*
>
>
>
![](https://img-blog.csdnimg.cn/20210924133718836.png)
#### 0x02 ASCII 码值
>
> 📚 ASCII (American Standard Code for Information Interchange)
>
>
> “是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符”
>
>
>
#### 0x03 转义字符
📚 转意字符顾名思义就是转变字符的意思。
![](https://img-blog.csdnimg.cn/20210924134142769.png)
💬 让斜杠就是斜杠:
int main()
{
printf(“c:\test\32\test.c”); //再加一个斜杠,规避转义字符检测
return 0;
}
>
> 🚩 运行结果: c:\test\32\test.c
>
>
>
💬 三字母词、输出单引号、ddd、xdd:
int main()
{
printf(“(are you ok??)\n”); // ??) – ] - 三字母词
printf(“%c\n”, ‘’'); //输出一个单引号
printf(“%s\n”, “”"); //输出一个双引号
printf("%c\n", '\130');//8进制的130是10进制的多少呢?
//X - ASCII码值是88
printf("%c\n", '\101'); // A- 65 - 8进制是:101
printf("%c\n", '\x30'); //48 - '0'
return 0;
}
>
> 🚩 运行结果: (are you ok??) ' " X A 0
>
>
>
❓ 下列代码打印的结果是什么?
int main()
{
printf(“%d\n”, strlen(“c:\test\328\test.c”));
return 0;
}
💡 答案:14
![](https://img-blog.csdnimg.cn/20210924134305142.png)
#### 0x04 注释
📚 代码中有不需要的代码可以直接删除,也可以注释掉
代码中有些代码比较难懂,可以加一下注释文字
有两种风格:
① C语言风格的注释 /\* xxxxxx \*/
缺陷:不能嵌套注释
② C++风格的注释 //xxxxxxxxx
优点:可以注释一行也可以注释多行
快捷键:*Ctrl + /?*
💬 演示:
/* C语言风格注释
int Add(int x, int y) {
int z = 0;
z = x + y;
return z;
}
*/
int Add(int x, int y) {
return x + y;
}
int main()
{
// C++注释风格
// int a = 10;
printf(“%d\n”, Add(1,2)); //调用Add函数
return 0;
}
### 五、分支和循环
#### 0x00 if 语句
📚 定义:if 语句是指编程语言(包括c语言、C#、VB、java、汇编语言等)中用来判定所给定的条件是否满足,根据判定的结果(真或假)决定执行给出的两种操作之一。
![](https://img-blog.csdnimg.cn/20210924134544362.png)
💬 选择语句代码演示:
int main()
{
int a = 10;
int b = 20;
if(a>b) {
printf("a比b大\n") ;
} else {
printf("b比a大\n");
}
return 0;
}
>
> 🚩 运行结果: b比a大
>
>
>
❓ C语言中如何实现循环呢?
1. while 语句
2. for 语句
3. do ... while 语句
这里我们着重先了解下 while 语句。
📚 while 循环的基本概念:while是计算机的一种基本循环模式。当满足条件时进入循环,进入循环后,当条件不满足时,跳出循环。
![](https://img-blog.csdnimg.cn/20210924134850782.png)
💬 演示代码:敲三万行代码
#include <stdio.h>
int main()
{
int line = 0;
while(line < 30000) {
printf(“敲代码: %d\n”, line);
line++;
}
if(line == 30000) {
printf(“恭喜你敲满30000行代码!\n”);
}
return 0;
}
### 六、函数
❓ 什么是函数?
数学中的函数 f(x) = 2×x+5,C语言中的函数也是一样的。
📚 函数的特点就是:简化代码,代码复用。
![](https://img-blog.csdnimg.cn/20210924135011705.png)
💬 代码演示:
int Add (int x, int y) {
int z = 0;
z = x + y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
scanf(“%d%d”, &num1, &num2);
// int sum = num1 + num2;
// 函数的方式解决
int sum = Add(num1, num2);
printf("%d\n", sum);
return 0;
}
### 七、数组
📚 要存储1-10的数字,怎么存储?
“C语言给了数组的定义:一组相同类型元素的集合”
定义一个整型数组,最多放十个元素:
![](https://img-blog.csdnimg.cn/20210924135150219.png)
💬 代码演示:
int main()
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
//…
// 10个整型1-10存起来
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
char ch[5] = {'a', 'b', 'c'}; // 不完全初始化,剩余的默认为0
// 用下标就可以访问元素
printf("%d\n", arr[0]);
// 打印整个数组
int i = 0;
while(i<10) {
printf("%d ", arr[i]);
i++;
}
return 0;
}
### 八、操作符简单介绍
#### 0x00 算数操作符
❓ 什么是算数操作符?
📚 算术运算符即算术运算符号。是完成基本的算术运算 (arithmetic operators) 符号,就是用来处理四则运算的符号。
![](https://img-blog.csdnimg.cn/20210924135347367.png)
💬 代码演示:
int main()
{
int add = 1 + 1;
int sub = 2 - 1;
int mul = 2 * 3;
float div = 9 / 2.0; //只要有浮点数出现,执行的就是浮点数除法
int mod = 123 % 10;
return 0;
}
#### 0x01 移位操作符
❓ 什么是移位操作符?
📚 移位运算符在程序设计中,是位操作运算符的一种。移位运算符可以在二进制的基础上对数字进行平移。
![](https://img-blog.csdnimg.cn/20210924135457148.png)
💬 代码演示:
int main()
{
// 移位操作符 移动的是它的二进制位
// << 左移
// >> 右动
int a = 1;
// 整形1占4个字节-32bit位
// 0000000000000000000000000000001
int b = a<<1;
// 0000000000000000000000000000010 左边丢弃,右边补0
printf(“%d\n”, b);
printf(“%d\n”, a);
return 0;
}
>
> 🚩 运行结果: 2 1
>
>
>
#### 0x02 位操作符
❓ 什么是位操作符?
📚 位操作是程序设计中对位模式按位或二进制数的一元和二元操作
![](https://img-blog.csdnimg.cn/20210924143419960.png)
💬 代码演示:
#include <stdio.h>
int main()
{
//位操作 依然是二进制位
// & 按位与 都为真,则返回真,只要出现假,就返回假
int a = 3; //真
int b = 5; //真
int c = a&b; //按位与
// 011
// 101
// 001
// R→ 1 //真
printf("%d\n", c);
int d = a|b;// 按位或 有真则为真,无则假,只要出现真,就返回真
// 011
// 101
// 111
// R→ 7
printf("%d\n", d);
int e = a^b;// 按位异或 相同为假,相异为真 11\ 00-> 0 10 -> 1
//异或的计算规律
//对应的二进制位相同,则为0
//对应的二进制位相异,则为1
// 011
// 101
// 110
// R→
printf("%d\n", e);
return 0;
}
#### 0x03 赋值操作符
❓ 什么是赋值操作符?
📚 赋值运算符是双目运算符,用在赋值表达式中。赋值运算符将值存储在运算符左边操作数指定的变量中。
![](https://img-blog.csdnimg.cn/20210924143659272.png)
💬 代码演示:
#include <stdio.h>
int main()
{
int a = 10;
a = 20; // “=” 赋值 “==” 判断相等
a = a+10; //1
a += 10; // 2
a = a-20;
a -= 20;
a = a & 2;
a &= 2;
//这些操作叫做 复合赋值符
return 0;
}
#### 0x04 单目操作符
❓ 什么是单目操作符?
📚 单目操作符,也就是只接受一个操作数的操作符。
![](https://img-blog.csdnimg.cn/20210924143753411.png)
💬 逻辑反操作 !
int main()
{
//0表示假,非0就是真
int a = 5;
printf(“%d\n”, !a);
if(a) {
//如果a为真,做事
}
if(!a) {
//如果a为假,做事
}
while(a); //a != 0,做事
while(!a); //a=0,做事
return 0;
}
💬 按位取反 ~
int main()
{
int a = 0;
printf(“%d\n”, ~a);
// ~ 按(二进制)位取法
//把所有二进制位的数字,1变成0,0变成1
//整数a
// 0
// 00000000000000000000000000000000
// 11111111111111111111111111111111 ~a
// 数据在内存中存储的是补码
// 一个整数的二进制表示有三种: 原码 反码 补码
// 负数的计算 -1:
// 10000000000000000000000000000001 (原码)
// 11111111111111111111111111111110 (反码)
// 11111111111111111111111111111111 (补码) -> 在内存中存的
// 正的整数: 原码、反码、补码相同
return 0;
}
💬 前置++
int main()
{
int a = 10;
int b = ++a; //前置++, 先++后使用
printf("%d\n", b); //11
printf("%d\n", a); //11
return 0;
}
💬 后置++
int main()
{
int a = 10;
int b = a++; //后置++,先使用再++
printf("%d\n", b);
printf("%d\n", a);
return 0;
}
💬 强制类型转换:
int main()
{
int a = (int)3.14; //强制类型转换
printf(“%d\n”, a);
return 0;
}
#### 0x05 逻辑操作符
📚 逻辑运算符或逻辑联结词把语句连接成更复杂的复杂语句
逻辑与:两个都为真即为真(and)
逻辑或:一个为真即为真(or)
![](https://img-blog.csdnimg.cn/20210928100013922.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p-g5qqs5Y-25a2QQw==,size_20,color_FFFFFF,t_70,g_se,x_16)
💬 逻辑与 &&
int main()
{
int a = 3;
int b = 5;
int c = a && b;
printf(“%d\n”, c); //1
return 0;
}
💬 逻辑或 ||
int main()
{
int a = 3;
int b = 0;
int c = a||b;
printf(“%d\n”, c); //1
return 0;
}
#### 0x06 条件操作符
📚 条件操作符就是三目操作符
exp1成立,exp2计算,整个表达式的结果是:exp2的结果。
exp1不成立,exp2计算,整个表达式的结果是:exp3的结果。
![](https://img-blog.csdnimg.cn/20210924144231369.png)
💬 条件操作符的用法:
int main()
{
//exp1成立,exp2计算,整个表达式的结果是:exp2的结果
//exp1不成立,exp3计算,整个表达式的结果是exp3的结果
int a = 0;
int b = 3;
int max = 0;
/* 等价于
if(a>b) {
max = a;
} else {
max = b;
}
*/
max = a>b ? a : b;
return 0;
}
#### 0x07 逗号表达式
📚 逗号表达式:逗号隔开的一串表达式。
逗号表达式是从左向右依次计算的。
整个表达式的结果是最后一个表达式的结果。
![](https://img-blog.csdnimg.cn/20210924144334662.png)
💬 逗号表达式的用法演示:
int main()
{
(2, 3+5, 6);
int a = 0;
int b = 3;
int c = 5;
// a=5 c=5-4 b=1+2
int d = (a=b+2, c=a-4, b=c+2);
printf(“%d\n”, d); // 3
return 0;
}
#### 0x08 下标引用操作符
📚 [] 就是下标引用操作符。
💬 演示:
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf(“%d\n”, arr[5]); // 6
return 0;
}
#### 0x09 函数引用操作符
📚 调用函数时,函数名后面的()就是函数调用操作符
💬 演示:
int main()
{
printf(“hehe\n”);
printf(“%d”, 100);
return 0;
}
### 九、关键字
#### 0x00 常见关键字
📚 C语言提供的关键字:
1. C语言提供的,不能自己创建关键字
2. 关键字不能做变量名
![](https://img-blog.csdnimg.cn/20210924144607268.png)
这里我们来简单地介绍几个:
💬 auto - 自动的
int main()
{
{
int a = 10; //自动创建,自动销毁的 - 自动变量
// auto省略掉了
auto int a = 10;
// auto新的C语言中也有其它用法 - 暂时不考虑
}
return 0;
}
💬 register - 寄存关键字
int main()
{
// 大量/频繁使用的数据,想放在寄存器中,提升效率
register int num = 100; //建议num的值存放在寄存器中
//是不是最终放到寄存器中是编译器说的算
// 其实现在编辑器已经很聪明了,
// 就算你不主动加register,它也会帮你存到寄存器中。
return 0;
}
💬 typedef - 类型重命名
// 这种罗里吧嗦的变量我们可以把它重命名一下
typedef unsigned int u_int;
int main()
{
unsigned int num = 100;
u_int num2 = 100; //和上面是等价的
return 0;
}
📚 static - 静态的
1. static修饰局部变量
2. static修饰全局变量
3. static修饰函数
💬 static修饰局部变量
函数中局部变量:
声明周期延长:该变量不随函数结束而结束
初始化:只在第一次调用该函数时进行初始化
记忆性:后序调用时,该变量使用前一次函数调用完成之后保存的值
存储位置:不会存储在栈上,放在数据段
void test() {
static int a = 1; //不销毁,生命周期变长了
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while(i<10) {
test();
i++;
}
return 0;
}
>
> 🚩 运行结果: 2 3 4 5 6 7 8 9 10 11
>
>
>
![](https://img-blog.csdnimg.cn/20210924144830872.png)
💬 static修饰全局变量
改变该变量的链接属性,让该变量具有文件作用域,即只能在当前文件中使用。
① Global.c:
static int g_val = 2021;
// static 修饰全局变量,
// 使得这个全局变量只能在自己所在的源文件(.c)内部可以使用
// 其他的源文件不能使用!
// 全局变量,在其他原文件内部可以被使用,是因为全局变量具有外部链接属性
// 但是被static修饰之后,就变成了内部链接属性,
// 其他的源文件就不能链接到这个静态的全局变量了!
② test.c:
extern int g_val;
int main()
{
printf(“%d\n”, g_val);
return 0;
}
>
> 🚩 运行结果: test.obj : error LNK2001: 无法解析的外部符号 \_g\_val
>
>
>
![](https://img-blog.csdnimg.cn/20210924145009647.png)
💬 static修饰函数
改变该函数的链接属性,让该函数具有文件作用域,即只能在当前文件中使用。
① Add.c:
//static修饰函数,
static int Add(int x, int y) {
return x + y;
}
💬 test1.c:
extern int Add(int, int); //声明外部函数
int main()
{
int a = 10;
int b = 20;
int sum = Add(a, b);
printf(“sum = %d\n”, sum);
return 0;
}
>
> 🚩 运行结果:
>
>
> test.obj : error LNK2019: 无法解析的外部符号 \_Add,该符号在函数 \_main 中被引用
>
>
>
![](https://img-blog.csdnimg.cn/20210924145142931.png)
#### 0x01 define
📚 define 是一个预处理指令:
1. define 定义标识符常量
2. define 定义宏
💬 define 定义标识符常量:
#define MAX 1000
int main()
{
printf(“%d\n”, MAX);
return 0;
}
💬 define 定义宏:
#define ADD(X, Y) X+Y
#define ADD1(X, Y) ((X)+(Y))
int main()
{
printf(“%d\n”, 4ADD(2, 3));
// 42+3 = 11
printf(“%d\n”, 4ADD1(2, 3));
// 4(2+3) = 20
return 0;
}
### 十、指针初探
## 学习路线:
这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成黑客大神,这个方向越往后,需要学习和掌握的东西就会越来越多以下是网络渗透需要学习的内容:
![在这里插入图片描述](https://img-blog.csdnimg.cn/7a04c5d629f1415a9e35662316578e07.png#pic_center)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**