(☞゚ヮ゚)☞精品C语言整理☜(゚ヮ゚☜)女盆友缠着你让你教她写代码怎么办?安排,三万字博文带你走遍C语言,从此不再害怕编程
Posted 紫寒C++
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(☞゚ヮ゚)☞精品C语言整理☜(゚ヮ゚☜)女盆友缠着你让你教她写代码怎么办?安排,三万字博文带你走遍C语言,从此不再害怕编程相关的知识,希望对你有一定的参考价值。
大家好,我🏁🏁Aaron, 对于学习编程的 hxd
们都有一个困扰,女朋友想了解你在干嘛却完全不懂代码怎么办,本文整理了C语言入门到进阶全知识点的概述以及基本用法,从此让你和女朋友一起幸福快乐的敲代码,该专栏后期会出C语言知识点详解和进阶和各种经典例题喔~感兴趣的朋友们可以订阅下来慢慢学习!!
✪ ω ✪ ✪ ω ✪
👍点赞👍 + 👀关注👀 + ✔收藏✔
正文开始(老爷点个收藏慢慢看~)
文章目录
前言
本文旨在完整介绍C语言所学内从,是C语言专栏中的第一版,有兴趣完整的,系统的学习C语言知识的读者可以订阅本专栏,博主将会努力整理,博主准备的C语言专栏总共有三版。本专栏会介绍到很多计算机底层知识,建议收藏,慢慢学习嗷!
本文目标:
基本了解C语言的基础知识,对C语言有一个大概的认识
每个知识点就是简单认识,不做详细讲解,专栏后期都会细讲
全文重点
- 什么是C语言
- 第一个C语言程序
- 数据类型
- 变量、常量
- 字符串 + 转义字符 + 注释
- 选择语句
- 循环语句
- 函数
- 数组
- 操作符
- 常见关键字
- define 定义常量和宏
- 指针
- 结构体
正文开始
一、什么是C语言
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
尽管C语言提供了许多低级处理的功能,但任然保持着良好的跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台
二十世纪八十年代,为了比年各开发厂商用的C语言语法差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法名称为ANSI C,作为C语言最初的标准,目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言最新的标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程
C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同
接下来介绍其中我们必须要了解和掌握的!其编译器主要有Clang、GCC、WIN - TC、MSVC、Turbo C等。
什么是C语言呢?
C语言就是一种计算机语言
我们如何理解计算机语言?
其实将计算机语言和我们日常的语言类比起来就很好理解了
- 计算机语言 - 人和计算机交流的语言(C/C++/Java/Python…)
- 语言 - 人和人交流的语言(汉语、英语、日语)
C语言广泛运用于底层开发
如图:
这里的应用软件的开发被称为顶层开发
操作系统、驱动、硬件的开发则被称为底层开发
任何一门没有国际标准的语言,都不能被称为一门好的语言,而C语言,恰好有!!
C标准:
C语言出现 --> C语言标准:
K & R
C89 --> C90 --> C98 --> C99 --> C11
二进制 --> 二进制代码 --> 助记符(汇编语言) --> B语言 --> C语言
二进制:用0/1表示
在早期,用一个二进制代码表示一种算法,如:
00001011 - 加法 - ADD
编程工具:编译器
- VC6.0 - 98年的软件(过于古老,不建议使用)
推荐使用:
- VS2013 / VS2019 - 企业中常用的编译器
IDE - 集成开发环境,调用的是底层的MSVC编译器
-
Linux - gcc
-
Linux - clang
-
DEV - C++ - 学校推荐的!!!不建议使用,已经十几年不再更新了
二、第一个C语言程序
写一个C语言代码步骤:
- 工具(编译器) - VS2019
如果有码友使用的是VS2013版本的编译器,可能会遇到程序运行结果一闪而过的情况
解决办法1:
设置项目属性 --> 链接器 --> 系统 --> 子系统 --> 控制台
解决办法2:
使用系统控制命令
system(“pause”);
# include <stdio.h>
# include <stdlib.h>
int main()
{
printf("hehe\\n");
//system是一个库函数
//是用来执行系统命令的
//pause - 暂定
system("pause");
return 0;
}
system是一个库函数,是用来执行系统命令的,需要调用
#include - - 头文件
pause - 暂停控制台的作用
- 写代码
- 创建项目
- 创建源程序
-
test.c - 源文件
test.h - header头文件 - 写出main函数
#include <stdio.h>
//stdio.h 是一个头文件的名称
//std - 标准,i - input,o - output
//标准输入输出头文件
int main() // int - 整型
{
//实际运行的代码
//打印hello world
//打印函数 - printf - 库函数,库函数的使用得引用头文件的
printf("hello world\\n");
return 0;
}
printf - 打印函数 - 库函数,库函数的使用得引用头文件
标准输入输出
stdio.h 是一个头文件的名称
std - 标准, i - input, o - output
- 运行代码
- 快捷键:
ctrl +F5 / ctrl + Fn + F5
- 按键
- 快捷键:
这里补充一点关于键盘上 Fn 键的知识
补充
Fn - 辅助功能键
F1 - F12本来是在变成中被赋予了相应的功能
但为了迎合大众小白用户的使用体验,有些键盘中赋给了F1 - F12键新的功能,如果想要使用这些键原本的功能,则需要按住 Fn + F1 - F12即可使用他们原本的功能
但这知识针对某些机器或者键盘所具有的功能辅助键,并不是所有的都需要这样操作
而且有的键盘上的 Fn 键是可以关闭的,可根据自身硬件采取相应措施
据博主目前测试,大部分笔记本电脑是会有 Fn 键的,而台式机基本都是应键盘而异,有的有,有的没有,有的像博主这样的,可以关闭,很方便,美滋滋。
C程序写法
写C语言代码时,虽然 VS2019 对 C99 标准并不是很支持,但我们现在敲代码基本采用 C99 的新写法为主,接下来展示C99和C89两种主函数的写法
# include <stdio.h>
//按F10
//main 函数是C语言程序的入口
//代码是从main函数的第一行开始执行的
//main函数有且只有一个
//C99 中引入的写法
int main()
{
printf("hello world\\n");
printf("hello world\\n");
printf("hello world\\n");
printf("hello world\\n");
printf("hello world\\n");
return 0;
}
// 早期的写法
void main()
{
}
main 函数是C语言程序的入口
代码是从main函数的第一行开始执行的
main 函数有且只有一个
并且 main 函数可以放在程序的任意位置
三、数据结构
C语言是计算机语言
使用计算机语言写代码 - 写程序
程序是用来干什么的? - 程序是用来解决我们日常生活中的问题的
解决我们生活中的问题,比如:
购物 - - 网上购物 - 网上商城 - 淘宝 - 京东
模拟生活中的购物,然后在网络上解决购物问题
写程序就是利用各种各样的算法来解决如同上述这样的问题,其实我们的网购就是利用了很多高级的算法和程序拼接在一起实现的
既然要解决日常问题,那我们在生活中的数据是各式各样的,如果C语言想要描述这些数据,就需要存在与之相匹配的数据类型
比如:
50 - 是整数 使用 int 整型类型
55.5 - 是小数 使用 float / double 浮点数类型
下面把C语言中的数据类型一一罗列:
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点型
double //双精度浮点型
我们在此可以思考一下:C语言中有没有字符串类型呢?
以下为C语言中数据类型的分类整理
字符类型
char
整型
short [int]
int
long [int]
long long [int]
浮点型
float - 单精度浮点型
double - 双精度浮点型
小数为什么在C语言中被称为浮点数呢?
123.45
12.345 * 10
1.2345 * 100
如上所示
因为小数点可以浮动,所以叫做浮点型
那么每种数据类型的所占内存空间大小是多少呢?
我们可以通过写代码来验证和计算
这里就要用到我们的 sizeof 操作符,一个专门用来计算占内存空间大小的操作符
代码如下:
#include <stdio.h>
int main()
{
//printf - %d - 打印有符号数
//printf("%d\\n", 100);
printf("%d\\n", sizeof(char));
printf("%d\\n", sizeof(short));
printf("%d\\n", sizeof(int));
printf("%d\\n", sizeof(long));
printf("%d\\n", sizeof(long long));
printf("%d\\n", sizeof(float));
printf("%d\\n", sizeof(double));
return 0;
}
这里注意, 如果 sizeof 的操作数是变量,括号是可以省去的,但如果 sizeof 的操作数是数据类型,这个括号不可以省略,否则会报出语法错误,无法通过编译的!!!
运行结果:
控制窗口打印了这些数字,那么他们的单位又是什么呢?
接下来就要介绍计算机中的单位了
计算机中的单位总共有如下这么几种:
bit byte kb mb gb tb pb
而我们的计算机能够识别的是二进制(0/1) --> 我们规定一个比特位只能存放一个二进制位,得出如下单位换算:
1byte = 8bit
1kb = 1024byte
1mb = 1024kb
1gb = 1024mb
1tb = 1024gb
1pb = 1024tb
sizeof 计算的单位是byte - 字节
C语言标准规定:
sizeof (long) >= sizeof (int)
sizeof (long long) >= sizeof (long)
在64位机器上:sizeof (long) = = 8
在32位机器上:sizeof (long) = = 4
所以 long 类型不一定比 int 类型大
而 long long 类型也不一定比 long 类型大
这都是要取决于代码处在多少位的机器上决定的。
那么为什么会出现这个多的类型呢?
其实很简单
举个例子:
钱的数目不同:可以有100元 10000元 10000000元 100亿
年龄大小可以不同:可以有 10 岁,20 岁,100岁
不同大小的值存放在不同的类型中,可以避免浪费内存
比如用一个 long long 类型的变量去存放一个数字 20 ,实在是有些铺张浪费了
又或者如果用 char 存放 100 亿,那也存不下呀,所以我们需要有灵活的数据类型存放不同的数据
代码展示:
#include <stdio.h>
int main()
{
int age += 20;//age 在内存中分配4个字节的空间
char ch = 'w';//ch 在内存中分配1个字节的空间
short = age;
//类型 变量名 值
int salary = 10000;
}
注意:存在这么多的类型,其实是为了更加丰富的表达生活中的各种值
四、 变量,常量
生活中有些值是不变的(比如:圆周率,性别(?),身份证号码,血型等等)。
有些值是可变的(比如:年龄,体重,薪资)。
不变的值,C语言中用常量的概念来表示,变的值C语言中用变量来表示。
4.1 变量的定义方法
定义一个变量,有一个固定的写法:
变量类型 + 变量名 + 赋初值
如:int a = 10;
代码展示:
#include <stdio.h>
int main()
{
int age = 20;
float weight = 55.8;
return 0;
}
4.2 变量的分类
变量分为两类:
- 全局变量
- 局部变量
下面用代码的形式给大家演示,方便理解
#include <stdio.h>
//全局变量 - 在大括号外部定义的变量就是全局变量
int a = 100;
//局部变量就是在main函数中定义的变量 - 对不对? - error
void test()
{
int b = 10;
}
int main()
{
//局部标量 - 在大括号(代码块)内部定义的变量就是局部变量
int a = 10;
printf("a = %d\\n", a);//局部变量和全局变量名字冲突(一样)的情况下,局部优先
return 0;
}
总结:
上面的局部变量global变量的定义其实是没有什么问题的!
局部变量和全局变量名字冲突(一样)的情况下,局部优先
全局变量 - 在大括号外部定义的变量就是全局变量
局部标量 - 在大括号(代码块)内部定义的变量就是局部变量
4.3 变量的使用
下面用代码的形式给大家展示变量在创建之后是如何使用的:
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
//printf()是输出函数 - 库函数
//scanf()是输入函数 - 库函数
//scanf函数要正常使用,就得在scanf所在的源文件的第一行加上#define _CRT_SECURE_NO_WARNINGS 1
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\\n", sum);
return 0;
}
大家在使用编译器写代码的时候,难免会经常遇到一个问题:
总用如下所示的安全警告
这就是函数不安全问题
解决方法1:在当前代码第一行加上
_CRT_SECURE_NO_WARNINGS
如果每次写代码都要复制一次,未免太过于繁琐,所以给出了一劳永逸的方法:
找到VS安装路径 --> 找到newc++file.cpp文件 --> 编辑文件,在文件中加上上面这句话
之后每次使用会自动生成
解决方法2:我们可以看到警告后面会提示我们使用 scanf_s 函数,但博主这里建议大家使用第一种方法,因为 scanf_s 是编译器里的函数,C语言各种版本中没有这种函数,所以以后如果我们将代码放在其他编译器上运行,就会跑不起来,是我们的代码不具有可移植性
其他不安全的函数:strcat / strcpy
那么为什么会出现不安全的现象呢?
给出不安全示范代码如下:
//%d - 整型
//%s - 字符串
int main()
{
char arr[5] = {0};//数组
scanf("%s", arr);
//scanf_s不是C语言的,是VS编译器提供的
//如果你的代码中使用了scanf_s函数,你的代码可能在其他的编译器上无法编译
printf("%s\\n", arr);
return 0;
}
运行结果:
如上述代码和运行结果可知,我们在定义数组的时候,只创建了大小为5的数组,而我们在输入的时候,如果输入的字符个数大于5,则会导致程序崩溃,这也就是函数为什么会不安全的原因
但是就算使用上述方法,也只不过是让编译器不再警告,也就是忽略警告的作用,让我们的代码可知正常跑过去,但我们还是要人为的控制输入字符的个数,不要让输入的字符过多,导致数组越界,程序崩溃。
4.4变量的作用域和生命周期
1)变量的作用域:
作用域(scope):程序实际概念,通常来说,一段程序中所用到的名字并不总是有效 / 可用的,而限定这个名字的可用性代码返回就是这个名字的作用域。
- 局部变量的作用域就是局部变量所在的局部范围
- 全局变量的作用域是整个工程
下面看两个代码解释:
代码1:
#include <stdio.h>
void test()
{
int b = 100;
}
int main()
{
{
int a = 10;
}
printf("a = %d\\n", a);
printf("b = %d\\n", b);
return 0;
}
这段代码的结果无法打印 a, b
因为 a 的作用域只能在自己的代码块内
b 只能在 test 函数内部使用
代码2
#include <stdio.h>
int g_val = 100;
void test()
{
printf("g_val = %d\\n", g_val);
}
int main()
{
printf("g_val = %d\\n", g_val);
test();
return 0;
}
可以打印两个 g_val = 100,因为 g_val 是定义在全局范围内的,在整个工程中都可以使用
生命周期:
变量的生命周期值指的是变量的创建到变量的销毁之间的一个时间段。
- 局部变量的生命周期是:进入作用域(局部范围)生命周期开始,出作用域(局部范围)生命周期结束。
- 全局变量的生命周期是:整个程序(main函数)的生命周期
#include <stdio.h>
int main()
{
{
int a = 100;
printf("1: a = %d\\n", a);
}
printf("2: a = %d\\n", a);
//程序的生命周期和main函数的生命周期是一样的
//全局变量的生命周期和程序,main函数的生命周期是一样的
return 0;
}
打印结果为 1:a = 100
局部变量 a 在进入代码块时创建,出这个代码块之后就会销毁,遇到第二个 printf 函数时已经不存在 a 这个变量了
全局变量演示:
test1.c
int g_val = 2000;
test2.c
#include <stdio.h>
//声明外部变量
extern int g_val; // -- extern 关键字是声明关键字,在做声明时使用
int main()
{
printf("g_val = %d\\n", g_val); // 2000
return 0;
}
以上代码说明:全局变量可以在不同的源文件内起效用,但需要在使用之前提前声明(使用 extern 关键字)
4.5 常量
C语言中的常量和变量的定义的形式有所差异
C语言中的常量分为以下几种:
- 字面常量
- const 修饰的常变量
- #define 定义的标识符常量
- 枚举常量
下面 一 一 介绍
- 字面常量
就是类似于普通数字一样的常量,无法改变
下面用代码演示:
#include <stdio.h>
int main()
{
"abcdef";
3.14;
100;
return 0;
}
- const 修饰的常变量
一个变量在被 const 修饰之后就会具有了常属性,但本质上还是一个变量
在C99版本之前,被const 修饰的变量不能放在数组中使用作为数组的大小
但是在C99版本之后,引入了变长数组的概念,可以将被 const 修饰的变量放在数组定义大小的方括号( [ ] )内使用
#include <stdio.h>
int main()
{
const int num = 10;
num = 20;//对常变量进行赋值, num 的值无法被修改
printf("%d\\n", num); // 结果依然是10
const int n = 10;// n 虽然被 const 修饰,但本质上还是一个变量,不能用来被指定为数组的大小(C99版本之前)
int arr[n] = {0};
//在C99标准之前,数组的大小只能是常量
//VS2019对C99支持的不是很好啊
//不支持变长数组,所以会报错
return 0;
}
在C99标准之前,数组的大小只能是常量,但是在C99版本之后,数组的大小可以用变量来表示,即为变长数组。
但是博主使用的编译器是: VS2019 ,而VS2019对C99标准支持的并不是很好啊,不支持变长数组,所以会报错,所以我们还是要对自己使用的编译器稍作了解,再结合不同的C语言标准版本去学习,效果才能最优!!!
- #define 定义的标识符常量
#define 定义的标识符常量其实就是给定一个符号,让他代表你在代码里想要表示的值,代码在编译过程中,会将所有的符号替换成给定的值
下面用代码给大家演示 #define 定义标识符常量的效果和用法:
#include <stdio.h>
#define MAX 100 // 注意用 #define 定义的时候,语句后面没有分号(;)
int main()
{
printf("%d\\n", MAX);
MAX = 200; // err, 不能改变
int arr[MAX] = {0};// 是可以的
return 0;
}
我们要注意在使用 #define 定义的时候,语句后面没有分号(;),并且在习惯上用 #define 定义的标识符,我们都用大写字母表示。
因为用 #define 定义的标识符常量其本质上还是一个常量,代码在编译的过程中只是将其替换,所以在定义数组大小的过程中是可以使用被 #define 定义的表示符常量的,而且并不是变长数组。
- 枚举常量
我们在生活中会遇到很多可以 一 一列举的常量,这些常量在C语言中就被称为枚举常量。
比如:
性别:男(MALE),女(FEMALE),保密(SECRET)
三原色:R,G,B
下面用代码演示枚举常量的用法:
#include <stdio.h>
//enum 枚举关键字
enum Sex
{
//枚举变量
MALE = 5, // 定义时赋初值是可以的
FEMALE,
SECRET
}; // -- 枚举常量的定义需要在代码块末端加上分号(;)
int main()
{
enum Sex s = FEMALE;
//MALE = 5; err 不能改,枚举是常量但可以在定义时赋初值
printf("%d\\n", MALE);
printf("%d\\n", FEMALE);
printf("%d\\n", SECRET);
return 0;
}
注意使用枚举关键字定义枚举常量时,代码块后面的分号不能少!!
我们在默认状况下打印 MALE, FEMALE, SECRET 时,打印的是 0, 1, 2,这是编译器默认的,而且其本质就是个常量,所以我们后期无法对其进行修改或者赋值,如果想要让枚举常量具有我们想让它有的值,只能用过在定义时就对其进行赋初值,赋成我们想要的值!
五、 字符串 + 转义字符
1.字符串
我们都知道数据类型有:char int long …
那么有没有字符串类型呢?
答案是C语言中没有字符串类型
C语言中字符串的表示形式:
“hello world!\\n”
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串
ps:字符串的结束标志是一个 ‘\\0’ ,在计算字符串长度的时候 \\0 是结束标志,不算作字符串的内容
字符串用法代码演示:
#include <stdio.h>
int main()
{
//"abcdef";
//字符串可以存放在字符数组中
char arr1[] = "abc";// 在字符串的末尾隐藏了一个\\0,这个\\0是字符串的结束标志
char arr2[] = {'a', 'b', 'c'};
printf("arr1 = %s\\n", arr1);
printf("arr2 = %s\\n", arr2);
return 0;
}
打印结果为:
我们可以通过试验发现,如果在 arr2 后面加上一个 ‘\\0’,则打印的结果会相同
原因是 arr2 中如果没有 \\0 判断字符串结束标志,那么就会继续访问内存中后面的内容,而这些内容都是编译器预先放进的随机值,当遇到内存中的 \\0 (或者 0) 时,就停下来。
为解释 \\0 的作用,下面再举一个例子,方便大家掌握,
代码:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abc";
cahr arr2[] = {'a'. 'b', 'c'};
//库函数 - strlen - string lenth
//string.h
int len1 = strlen(arr1);
int len2 = strlen(arr2);
printf("len1 = %d\\n", len1);
printf("len2 = %d\\n", len2);
return 0;
}
打印结果:
首先 strlen 是一个计算字符串长度的库函数,在遇到 \\0 后就停下来,计算遇到 \\0 之前访问过得字符个数。len1 是 3很好理解,但是 len2 为什么是15呢?其实他的值不是永远都是 15 的,而是一个大于等于 3 的随机值
因为 arr2 中没有 \\0 ,所以 strlen 函数会继续越界访问内存中的其他后面的内容,直到访问到内存中存放的 0 (或者 \\0),就停下来,计算访问过的字符的个数,也就是字符串的长度
len1 :a, b, c, \\0 在算到 \\0 之前有3个字符,所以 len1 = 3;
len2 :a, b, c, …在 c 后面没有 \\0 ,所以会一直访问内存后面的内容,遇到 \\0 之前访问了 15 个数,是随机的。
再给出一个代码:
下面代码,打印的结果是什么?为什么?
(突出 ‘\\0’ 的重要性)
#include <stdio.h>
int main()
{
char arr1[] = "bit";
char arr2[] = {'b', 'i', 't'};
ShaderJoy —— 果冻般的弹性 “抖抖抖“ 特效GLSL