IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 初识C语言(三)--最终章,万字解析,趣味讲解完C语言的最后知识点 -> 正文阅读

[C++知识库]初识C语言(三)--最终章,万字解析,趣味讲解完C语言的最后知识点

前言
👻作者龟龟不断向前
👻简介宁愿做一只不停跑的慢乌龟,也不想当一只三分钟热度的兔子。
👻专栏C++初阶知识点

👻工具分享

  1. 刷题: 牛客网 leetcode
  2. 笔记软件:有道云笔记
  3. 画图软件:Xmind(思维导图) diagrams(流程图)

在这里插入图片描述

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主🙊,如有不足还请指点,博主及时改正

初识C语言(三)

🚀1.函数

? 如果你是一个懒人,而你的main函数里面有大量的重复操作,比如大量的加法计算。如下

#include<stdio.h>

int main()
{
	int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;
	int sum1 = a + b;
	int sum2 = c + d;
	int sum3 = e + f;
	printf("sum1 = %d\n", sum1);
	printf("sum2 = %d\n", sum2);
	printf("sum3 = %d\n", sum3);
	return 0;
}

? 而且这仅仅是一个加法,如果以后是更加复杂的操作,而且要重复的进行很多次,这是懒人所不能接受的的?严重破坏了懒人主义,我马爹也不同意,这个时候我们可以设计一个函数,每次要进行这个操作的时候,调用这个函数帮我们完成即可。

在这里插入图片描述

🍉函数的用法

#include<stdio.h>

int Add(int x,int y)
{
	return (x + y);
}

int main()
{
	int a = 1, b = 2, c = 3, d = 4, e = 5, f = 6;
	int sum1 = Add(a, b);
	int sum2 = Add(c, d);
	int sum3 = Add(e, f);
	printf("sum1 = %d\n", sum1);
	printf("sum2 = %d\n", sum2);
	printf("sum3 = %d\n", sum3);
	return 0;
}

? 函数的特点就是简化代码,代码复用。 目光要放长远,虽然这个例子我们还没有看到函数的太大作用,但是函数绝对是程序中必不可少的环节。

🍉函数的执行流程

? VS编译器,我们点击F10(有些同学需要配合Fn键使用)进入调试

在这里插入图片描述

? 目前程序已经执行到了int sum1 = Add(a,b)这个语句,这个时候sum1的值也没有计算出来,还是随机值。我们点击F11进入函数内部!

在这里插入图片描述

? 当我们继续点击F11,出了函数,return (x+y)就是将 x + y的值返回,而sum1接受了这个返回值,从而将sum1计算出来了。

在这里插入图片描述


🚀2.数组

顾名思义:一组相同类型元素的集合

问题:要存储1-10的数字,怎么存储?

虽然也可以如下暴力解决

#include<stdio.h>

int main()
{
    int a1 = 1;
    int a2 = 2;
    //…………创建10int类型的变量,放1~10的数字
    return 0;
}

? 很明显上述的代码显得非常搓,给人的印象很不好,那么数组的概念就可以很好地解决上述问题

🍉数组的创建/数组元素访问

数组的定义/创建:类型 数组名 [元素个数]–int arr[10]这里的元素个数必须是常量,整数

数组的元素访问:数组名 [下标],arr[6]注意下标是从0开始的,例如第7个元素的下标是第6和元素,这里的下标可以是变量,也可以是常量

注意:数组的定义和数组元素的访问都有[],但他们的作用是不同的

#include<stdio.h>

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	printf("%d\n", arr[6]);//下标访问操作符(常量变量都可以)
	int i = 0;
	while (i < 10)
	{
		printf("%d ", arr[i]);
		++i;//不要忘记调整i哟
	}
	printf("\n");

	return 0;
}

? 上述数组的初始化可以直接赋值,将一个集合(这个跟我们数学上的集合枚举法写法是已知的)赋值给数组。

在这里插入图片描述

?

在这里插入图片描述

? 当然了,上述数组创建的时候元素个数是可以不写的,编译器可以通过初始化时的元素个数,计算出来[]里面的值。


🚀3.操作符

🍉C操作符大全

? C语言之所以很灵活,一方面就取决于其丰富的操作符!

算术操作符

+ - * / %

移位操作符

>> <<

位操作符

& ^ |

赋值操作符

= += -= *= /= &= ^=  |=    >>=   <<=

单目操作符

!           逻辑反操作
-           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
(类型)       强制类型转换

关系操作符

>
>=
<
<=
!=   用于测试“不相等”
==   用于测试“相等”

逻辑操作符

&&     逻辑与
||     逻辑或

条件操作符

exp1 ? exp2 : exp3

逗号表达式

exp1, exp2, exp3, …expN

下标引用、函数调用和结构成员

[] () . ->

? 当然这些操作符也不要求死记硬背,也不要求现在就要都会用,咱们以后的学习中都会学习到,用到的。


🍉常见操作符的用法介绍

🍇/–求商 %–求余数(算术操作符)
#include<stdio.h>

int main()
{
	int m = 17;
	int n = 4;
	int q = m / n;//商
	int r = m%n;//取模--余数
	printf("%d\n", q);
	printf("%d\n", r);
	return 0;
}

扩展

这里给大家扩展一下,%操作符还是很常用的,经常会用到以下问题里面:

  1. 判断一个数是否能被另一个数整除–应用:用逢7,计算闰年
  2. 求两个数的最大公因数
  3. …………
🍇&&–并且 ||–或者(逻辑操作符)

exp1 && exp2–这个表达式中,exp1exp2都为真,整个表达式才为真,否则为假

exp1 && exp2–这个表达式中,exp1exp2只要有一个为真,整个表达式才为真,否则为假

计算机看不懂“真”,“假”,计算机判断条件真假是,0为假,非0为真

而我们传说中的if语句和while语句,if(条件),while(条件),他们他们的条件为真时,{}里面的语句才能被执行

&& 和 ||的理解有很多种

  1. 有些同学理解成botheither
  2. 有些同学理解成并且/都或者
  3. 有些同学理解成电路中的串联并联

大家用适合自己理解的去理解即可

在这里插入图片描述

举例1:

#include<stdio.h>

int main()
{
	int a = 1;
	int b = 2;
	if (a && b)
	{
		printf("你们两都来啦\n");
	}
	else
	{
		printf("你们两怎么没都来");
	}
	return 0;
}
int main()
{
	int a = 0;
	int b = 0;
	if (a || b)
	{
		printf("你们两至少有一个来了\n");
	}
	else
	{
		printf("你们两怎么没有一个人来\n");
	}
	return 0;
}

举例2:



int main()
{
	int age = 0;
	printf("请输入你的年龄\n");
	scanf("%d", &age);
	//if (18 <= age <= 36)//逻辑相差很大
    if (age >= 18 && age <= 36)
	{
		printf("你是青年\n");
	}
	else
	{
		printf("你不是青年\n");
	}
	return 0;
}

这里比较容易错,大家如果想要表示一个18-36的范围,千万不要像数学中一样直接来一手18 <= age <= 36,这是一个错误的逻辑,&&是一个二元操作符,一次只能进行两个操作数的操作,无法达到我们一次到位的效果

正确写法: if (age >= 18 && age <= 36)


🍇条件操作符exp1 ? exp2 : exp3

? 下面的图片可以大致解释条件表达式的意思

龟龟小故事:小明和小刚同时爱上了小红,小红也不知道怎么选择,于是绝对让小明和小刚做一个竞争,

小明赢了,那么小红就选择小明,小明输了(小刚赢了),小红就选择小刚

在这里插入图片描述

在这里插入图片描述

代码举例:

#include<stdio.h>

int main()
{
	int a = 3;
	int b = 10;
	int c = a > b ? a : b;
	printf("c = %d\n", c);
	return 0;
}

上述代码中,如果 a > b,则c = a,否则 c = b


正经解释:

条件表达式也叫做三目表达式,因为操作数有三个

exp1?exp2:exp3,如果exp1表达式的值为真,那么整个表达式的值就是exp2的值,否则整个表达式的值就是exp3的值

所以我们的求两数的最大值的函数可以稍微改善一下了:

改善前:

int Max(int x, int y)
{
	if (x > y)
	{
		return x;
	}
	else
	{
		return y;
	}
}

改善后:

int Max(int x, int y)
{
	return x > y ? x : y;
}

龟龟小故事的结局与条件表达式无关😅

在这里插入图片描述
由于龟龟故事的结局有一点点大转变,审核警告我说我有点狂,所以大家可以去我仓库看龟龟小故事结局


🚀4.C关键字大全

? 我们按照类型,循环,分支对关键字进行一个分类

void

1.与类型有关的关键字

修饰类型autostaticconstexternsizeofsignedtypedefunsigned
内置类型chardoubleshortfloatintlongregister
自定义类型unionstructenum

2.与分支有关的关键字

casedefaultelsegotoifswitch

3.与循环有关的关键字

breakcontinuedoforwhile

剩下的关键字还有

void return volatile

? 这些关键字也是不需要死记硬背,后面我们都会用上


🚀5.scanf的返回值

? 有些同学可能会有疑惑,scanf–不是scan format不是格式化输入函数吗?怎么还有返回值

🍉成功输入

? 确实是有的,scanf的返回值为成功输入的元素个数

#include<stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	int ret = scanf("%d %d", &a, &b);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述


🍉输入失败

? 有成功输入的情况肯定也有输入失败的情况

在这里插入图片描述

? 上述操作我们只成功输入了一个数据,那么返回的是1

那要是全部输入失败了呢?

在这里插入图片描述

? 我们发现全部输入失败,scanf会返回-1,而不是0。起始scanf在全部输入失败时返回的时EOF,而EOF被做了一些操作

在这里插入图片描述

我们将鼠标放在EOF上面,发现define EOF -1EOF时#define定义的标识符常量。EOF的值本质就是-1


🍉解决OJ测试题多组测试用例输入

这里给大家推荐OJ刷题网站:牛客网,leetcode

在这里插入图片描述

这里我们看到的是多组输入,单组输入其实是无法解决该问题的

解决方法:

#include<stdio.h>

int main() {
    int num = 0;
    while(scanf("%d",&num) != EOF)//将scanf放在这里
    {
        if(num >= 60)
        {
            printf("Pass\n");
        }
        else
        {
            printf("Fail\n");
        }
    }
    return 0;
}

🚀6.关键字register的用法(如今作用不大)

🍉计算机存储金字塔层次结构

? 首先我们得介绍寄存器,高速缓存,内存,硬盘的区别

图解计算机存储金字塔层次结构

在这里插入图片描述

? 图中的L1,L2,L3就是高速缓存

平时我们所说的512GB就是电脑的硬盘,16GB叫做内存(手机上习惯叫运行内存)当然了我们现在还有所谓的网盘,网盘就在硬盘之下了。

一般的我们写代码向内存申请一块空间,然后创建一个变量,这个变量是存在内存中的,如果我们想提高效率,提高访问速度,可以在变量的类型前面,使用**register修饰** ,这样就可以 建议编译器将变量放到寄存器存储,从而提高访问效率吧

#include<stdio.h>

int main()
{
	register int a = 0;
	return 0;
}

? register int a = 0;–当然了这只是对编译器的一种建议,现在编译器还是比较聪明的,**会自动将一些下面要用到的变量存在寄存器。**可以理解register现在几乎作用不大。


🚀7.关键字typedef

功能就好像是:

在这里插入图片描述

在这里插入图片描述

就是取了个别名,但是并不是可以给任何东西取别名

typedef 顾名思义是类型定义,这里应该理解为类型重命名

例如我们可以将一些复杂的类型名重命名以下

#include<stdio.h>

typedef unsigned int uint;
int main()
{
	unsigned int a = 0;
	uint b = 0;
	return 0;
}

🚀8.关键字static

🍉static修饰的局部变量

题目测试:

#include<stdio.h>

void test()
{
	int a = 0;
	++a;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		++i;
	}

	i = 0;
	while (i < 10)
	{
		test();
		++i;
	}
	printf("\n");
	return 0;
}

? 同学们可以思考一下上述代码的输出结果是什么?

答案是是个1,你答对了吗?

1 1 1 1 1 1 1 1 1 1

原因解释:

? 因为我们讲过,局部变量的作用域是局部变量所在的局部范围–也叫代码块,当出了这个代码块,变量就会销毁,所以我们每次进入test函数,a都是重新创建的a,然后从0到1。

? 如果我们想要达到输出1~10的效果,就要让a的生命周期延长,使其出了代码块也不销毁,static就起作用了。

#include<stdio.h>

void test()
{
	static int a = 0;
	++a;
	printf("%d ", a);
}

int main()
{
	int i = 0;
	while (i < 10)
	{
		test();
		++i;
	}

	i = 0;
	while (i < 10)
	{
		test();
		++i;
	}
	printf("\n");
	return 0;
}

? 这里还是稍微解释一下static修饰的局部变量生命周期延长了。

🍉内存分区

在这里插入图片描述

? int a = 0;这个局部变量a是放在栈里面的,出了代码块a就会销毁,而static int a = 0这个a是放在静态区的,静态区的生命周期是从变量创建开始到程序结束,不归栈管,出了代码块a也没有销毁


🍉static修饰的全局变量

? 之前我们讲过全局变量的作用域是整个工程,具有外部链接属性,外部源文件也是可以使用当前源文件的全局变量的

在这里插入图片描述

在这里插入图片描述

? 如果我们将上述的global使用static修饰,那么global的外部连接属性也就消失了,也相当于作用域被缩小了

static int global = 100;

在这里插入图片描述


🍉static修饰函数

? 我们知道函数是具有外部链接属性的,而经过static修饰的函数,也会达到跟static修饰全局变量一样的效果,外部连接属性消失

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


🍉static的作用总结

1.static修饰局部变量,使得变量的内存存储方式改变了,从栈区存到了静态区,生命周期被延长,出了局部范围也不销毁

2.static修饰全局变量,使得变量的作用域缩小了,失去了外部链接数序,只能在本源文件中使用该变量

3.static修饰函数,使得变量的作用域缩小了,失去了外部链接数序,只能在本源文件中使用该函数
4.static可以影响生命周期,但是不会影响生命周期

? 全局变量和函数的下场就像,两个活泼的孩子,最近来疫情了,static妈妈管住他们,不让他们再往外面跑。居家隔离

在这里插入图片描述


🚀9.#define定义标识符和宏

🍉定义标识符

#define M 100
#include<stdio.h>

int main()
{
	int a = M;
	int arr[M];
	printf("%d\n", a);
	printf("%d\n", M);
	return 0;
}

? 这个很简单咱们在讲常量的时候已经讲过了。


🍉定义宏

宏的用法跟函数的用法差不多,就是定义的时候有些许差别,咱们点到位置

#define ADD(x,y) (x+y)
#define MAX(x,y) (x>y?x:y)
#include<stdio.h>

int main()
{
	printf("%d\n", ADD(3, 5)*8);
	printf("%d\n", MAX(10, 20)*8);
	return 0;
}

🚀10.C指针

? 想要清楚指针,我们进一步的了解内存

🍉内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。 所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。 为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。

例如我们拿32位机器举例,x86–32位机器,拥有32根地址线,这些地址线一共有两种状态,通路与断路,1/0,根据数学知识

一共就存在00000000 00000000 00000000 00000000 ~ 11111111 11111111 11111111 11111111共2^32中状态

就有2^32次方个内存编号,由于二进制的繁琐型,我们通常使用十六进制来表示地址

在这里插入图片描述

思考:32位机器下的内存大小是多少?

答案是4GB,清楚内存单位的换算即可

? 我们也可以使用敲代码,讲变量的地址打印在屏幕上:

在这里插入图片描述


? 而且我们可以调开vs的内存窗口看看效果

在这里插入图片描述

有些同学可能会疑惑,为什么两次运行程序,a的地址会不一样呢?

同学们思考一下,你去一家酒店开房,每次去,老板给你开的房都是同一间吗?不太可能对吧因为其他房间可能被占用着

同样的,每次申请空间也并不是一直给你的是那块内存,可能那块内存其他程序正在使用着


🍉指针变量

? 那我们使用能使用变量将地址存储起来呢?答案是可以的,但是有两个问题:指针变量是什么类型?指针变量的大小是什么?

🍇指针变量的类型
#include<stdio.h>

int main()
{
    int a = 10;
    int* p = &a;
    return 0;
}

? 如果指针变量存储的是一个int类型的地址,那么指针变量的类型就是int*,同理我们可以推出如何存储double,char类型的数据

#include<stdio.h>

int main()
{
    int a = 1;
    double b = 2.2;
    char c = 'w';
    
    int* pa = &a;
    double* pb = &b;
    char* pc = &c;
    return 0;
}

🍇指针变量的大小

? 是否还记得sizeof操作符

int main()
{
	int a = 1;
	double b = 2.2;
	char c = 'w';

	int* pa = &a;
	double* pb = &b;
	char* pc = &c;

	printf("%u\n", sizeof(pa));
	printf("%u\n", sizeof(pb));
	printf("%u\n", sizeof(pc));
	printf("%u\n", sizeof(int*));
	printf("%u\n", sizeof(double*));
	printf("%u\n", sizeof(char*));

	return 0;
}

答案都是:4(32位机器下)

%u – 打印32位机器下的无符号整形

%zd–打印64位机器下的无符号整形

这跟指针变量里面放的什么有关系,指针变量里面存放的是地址,地址是内存编号

32位机器下是32个bit的0/1数字,32位机器下是64个bit的0/1数字,根据 1byte = 8bit

所以32位机器下指针大小是4byte,所以64位机器下指针大小是8byte


🍇指针的使用

同学们想一想,如果你知道了你朋友家的地址,你把这个地址记在你的小本本上,那么你是不是可以就可以通过这个小本本上面的地址找到你朋友家。如果朋友家没锁,是不是还可以干点其他事儿,当然这是现实生活中不允许的对吧

同样的,如果我得到了a的地址,那么我是否可以通过这个地址找到a,对a进行一些操作呢,答案是可以的

#include<stdio.h>

int main()
{
	int a = 1;
	double b = 2.2;
	char c = 'w';

	printf("a = %d\n", a);
	printf("b = %.2f\n", b);
	printf("c = %c\n", c);

	int* pa = &a;
	double* pb = &b;
	char* pc = &c;
	*pa = 8;
	*pb = 4.4;
	*pc = 'z';
	printf("a = %d\n", a);
	printf("b = %.2f\n", b);
	printf("c = %c\n", c);
	return 0;
}

在这里插入图片描述


🚀11.结构体struct

前面我们介绍数据类型的时候提到了内置类型–C语言提高给我们可以直接使用的类型

例如int,double,char,生活中有一些数据我们使用内置类型无法定义,例如学生,汽车等

那么我们就要自己设计类型–自定义类型啦,开造

ps:我们可以自定义类型,但是不可以自己造一个关键字的哈

使用关键字struct

struct Stu
{
    char name[20];//名字
    int age;      //年龄
    char sex[5];  //性别
    char id[15]//学号
};

如果我们自己定义的类型:

#include<stdio.h>

struct Stu
{
    //成员变量
    char name[20];//名字
    int age;      //年龄
    char sex[5];  //性别
    char id[15]//学号
};

int main()
{
    //打印结构体信息
    struct Stu s = {"张三"20"男""20180101"};
    //.为结构成员访问操作符
    printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
    //->操作符
    struct Stu *ps = &s;
    printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps-
    >id);
    
    return 0;
}

struct Stu这个整体是一个类型名

在结构体变量右面加.可以访问其成员变量

在结构体指针变量(存放结构体变量的地址)右面加->可以访问其成员变量

点赞

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 20:56:54  更:2022-10-22 20:57:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 6:22:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码