计算机入门之C语言入门必看 与 C语言简单知识点复习专用
@
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
如何进军计算机行业从这篇文章开始。
1.为什么要学c语言
原因很简单:c语言是大多数高级语言的鼻祖,学会c语言学习其他语言事半功倍,C语言是母体语言,是人机交互接近底层的桥梁。
在IT行业,一般每10年就有一次变革近50年间,在TIOBE 排行榜中,C/C++位置长期霸占前三名,没有丝毫撼动,可谓经典永不过时!
所以作为入行计算机的同学来说,C语言是必学的。
2.编译器的选择
在这里本人推荐使用 vs2019 (集成开发环境) 作为日常学习的编译器
在高校中往往推荐学生使用 dev c++,本人一直用的vs2019,去使用dev c++之后只能说 vs 像现代人,dev c++像远古人=.= dev c++在使用方面远远没有vs2019来的顺畅,好用。
下面是vs2019的安装教程,看到这里可以试着安装一下啦。
[vs2019安装教程](VS2019的安装和简单使用-visual studio 2019 安装教程_哔哩哔哩_bilibili)
3.什么是c语言
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。C语言是一门面向过程的计算机编程语言。
可以简单的理解为一门低层语言,例如windows系统就是以c/c++语言制作的
4.第一个c语言程序
#include<stdio.h>
int main()
{
printf("hello world!");
return 0;
}
几乎每一位同学刚学的时候打的都是helloworld吧 ,可为什么要这么打呢?
让我们一一认识每一个符号的涵义吧!
#include 是头文件包含指令 理所应当 stdio.h 便是头文件了
注意 这里头文件包含要用**< >来包括stdio.h**这个头文件。
.h是头文件的后缀,每一个头文件最后都有**.h**。
main是一个函数,在c语言中该函数时作为c程序的入口,一个c语言程序有且仅有一个main函数(切记)
{…}里的内容就是我们的代码啦。
printf又是什么呢? printf是一个打印函数。
他的头文件是stdio.h, 这也是我们为啥要包含头文件的原因,不包含printf的头文件便无法使用printf。
printf函数使用的格式是(“需要打印的内容”)。
return 0;是函数结束的标志。
5.c语言数据类型
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
为啥我们需要这么多数据类型呢?
日常生活中,我们的交流用的只有数字与符号组成的语言
char提供了字符的数据类型
int 以及 double 等等数据类型则提供了能满足数字的各种需求的整形数据类型与浮点数数据类型。
数据类型的使用
#include<stdio.h>
int main()
{
char ch = "w"; // ch 是名称,而w是该ch中存贮的内容
int b = 10; // b 是名称,10 是b的存贮的内容,也就是b = 10
double a = 20; //同上
return 0;
}
那每一个数据类型的大小又是多少呢?
认识一下c语言关键字 sizeof(注意 不是函数)
sizeof它是一个运算符,其作用是取得一个对象(数据类型或者数据对象)的长度(即占用内存的大小,以byte为单位)。
普及下 计算机单位的换算
bit(比特) 是计算机最小的单位
8 bit = 1 byte(字节)
1024 byte = 1 kb
1024 kb = 1mb
1024mb = 1gb
…
可见sizeof运算的结果的单位是字节
#include <stdio.h>
int main()
{
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));
printf("%d\n", sizeof(long double));
return 0;
}
可见 各个数据类型的大小。值得探讨的是为什么long与int都是4呢?
实际上long的大小>=int的大小。
!!!c语言是没有字符串数据类型的
6.变量,常量
变量
定义变量
#include<stdio.h>
int main()
{
int age = 0;//定义一个int类型的变量,将变量的值初始化为0;
int age; //定义一个 int 类型的变量,但是不初始化,里面存放随机值
char ch = "w"; //定义一个 char类型的变量,初始化为字符”w”
return 0;
}
如代码块 ,定义变量时,需要为变量确定数据类型
变量的分类
变量分为
-
全局变量
-
局部变量
#include<stdio.h> int a = 100;//定义全局变量 int main() { int b = 2;//定义局部变量b int a = 10;//定义局部变量a printf("%d",a); }
大家可以在自己的编译器试一下当全局变量与局部变量名称相同时,是否会报错
如果不会报错,那打印的结果又是什么呢
结果显而易见是 10。
这里我们可以得到两个结论
-
上面的局部变量与全局变量的定义其实没有什么问题。
-
当局部变量和全局变量同名的时候,局部变量优先使用。
变量的使用
变量是用来存贮数值的。
那我们怎么将自己想要的数值赋值给变量呢?
接下来介绍scanf函数(格式输入函数)
scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。
scanf函数的一般形式为: scanf(“格式控制字符串”, 地址表列);
%d 用于接受 输入后a,b的值。值得注意的是,与打印函数printf函数不同,scanf函数接收a,b的值时,需要在a,b的前面加上&(取地址符号),只有这样才能完成对整形 a,b的输入
扩展:
- %d表示其输出格式为十进制有符号整数。
- %f表示其输出格式为浮点数。
- %lf同%f,表示浮点数。但是它是用在输入函数scanf中的,而%f则是用在输出函数printf中的。
- %c表示输出格式为字符。
- %s表示其输出格式为字符串。
变量的作用域与生命周期
作用域与生命周期是什么意思呢?
- 作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
接下来用代码来理解他们的语法
可以看到局部变量 i 在mian函数中可以使用,但是在test 函数中却无法使用。
这里涉及了c语言局部变量的作用域与生命周期的知识
-
. 局部变量的作用域是变量所在的局部范围。
同时,局部变量创建以后,在出了代码块以后,会自动销毁。得出:
-
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
全局变量在test函数与main函数中均能使用并且不会报错
得出:
-
全局变量的作用域是整个工程。
-
. 全局变量的生命周期是:整个程序的生命周期。
这里涉及了c语言局部变量的作用域与生命周期的知识
-
. 局部变量的作用域是变量所在的局部范围。
同时,局部变量创建以后,在出了代码块以后,会自动销毁。得出:
-
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
[外链图片转存中…(img-g4LWVQFB-1635483271198)]
全局变量在test函数与main函数中均能使用并且不会报错
得出:
C语言中的常量分为以下以下几种:
-
字面常量
-
const 修饰的常变量
-
#define 定义的标识符常量
-
枚举常量
用代码理解几种常量
#include<stdio.h>
int main()
{
3.14;//字面常量
1000;//字面常量
const float a = 1.28f; //const修饰的常量
//a = 1000; //error;常量不能修改大小。
#define MAX 100; //define 修饰的常量
return 0;
}
这里需特别注意:
定义数组时数组大小是常量,但是由const修饰的常量a却无法放在数组之中,会报错。
原因是:const修饰后的变量,虽然有了常量的属性,但是本质还是变量,一般叫为const修饰的常变量。既有常量的属性,也有变量的属性。
7.字符串+转义字符
字符串
"helloworld!"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字
符串。
注:字符串的结束标志是一个\0的转义字符。在计算字符串长度的时候\0是结束标志,不算作字符串内容。
#include<stdio.h>
int main()
{
char arr1[] = "bit";
char arr2[] = { 'b','i','t','\0' };
char arr3[] = { 'b','i','t' };
printf("%s\n", arr1);
printf("%s\n", arr2);
printf("%s\n", arr3);
return 0;
}
由代码与结果
我们可以很明显得看出,arr3由于没有\0,所以该数组最后得结果并不是bit,而是bit之后得一堆乱码,
原因是字符串数组结束得标志是\0,由于在打印得时候没有检测到bit后面得\0,程序会一直打印后面得字符直到遇到\0再终止。
转义字符
由一个问题引入
打印一个目录:c:\code\test.c
一般思路:
#include<stdio.h>
int main()
{
printf("c:\code\test.c\n");
return 0;
}
运行结果:
这背后打印失败得原因就是:转义字符的锅。
我们来认识下转义字符
? 在书写连续多个问号时使用,防止他们被解析成三字母词
\’ 用于表示字符常量’
\” 用于表示一个字符串内部的双引号
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符。
\a 警告字符,蜂鸣
\b 退格符
\f进纸符
\n换行
\r回车
\t水平制表符
\v垂直制表符
\dddddd表示1~3个八进制的数字。 如: \130 X
8\xdddd表示2个十六进制数字。 如: \x30 0
转义字符的存在是为了让编译器更好的运行了。
接下来怎么打印 c:\code\test.c
#include<stdio.h>
int main()
{
printf("c:\\code\\test.c\n");
return 0;
}
这样就成功啦。
普及注释的内容
C++风格的注释
// xxxxxxxx
可以释一行也可以注释多行
8.选择语句
(只介绍一种)
**if语句**
1) 第一种形式为基本形式:if
if(表达式) 语句
其语义是:如果表达式的值为真,则执行其后的语句,否则不执行该语句。其过程可表示为下图。
- 代码演示:
#include<stdio.h>
int main()
{
int a = 0;
scanf("%d",a);
if(a==1) //if中表达a=1时执行语句要用 == 号。在程序中的= 是赋值。
{
printf("好好学习");
}
return 0;
}
第二种形式为: if-else
if(表达式)
语句1;
else
语句2;
其语义是:如果表达式的值为真,则执行语句1,否则执行语句2 。其执行过程可表示为下图。
代码演示:
#include<stdio.h>
int main()
{
int a = 0;
scanf("%d",a);
if(a==1) //if中表达a=1时执行语句要用 == 号。在程序中的= 是赋值。
{
printf("好好学习");
}
else //else 输入a不为1时,执行后面语句
{
printf("不好好学习");
}
return 0;
}
-
第三种形式为if-else-if形式
前二种形式的if语句一般都用于两个分支的情况。当有多个分支选择时,可采用if-else-if语句,其一般形式为:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
…
else if(表达式m)
语句m;
else
语句n;
其语义是:依次判断表达式的值,当出现某个值为真时,则执行其对应的语句。然后跳到整个if语句之外继续执行程序。 如果所有的表达式均为假,则执行语句n。然后继续执行后续程序。 if-else-if语句的执行过程如下图所示。代码演示:
#include<stdio.h> int main() { int a = 0; scanf("%d",a); if(a==1) //if中表达a=1时执行语句要用 == 号。在程序中的= 是赋值。 { printf("好好学习"); } else if(a==2) //当a==2时 执行本else if后面语句 { printf("玩游戏"); } else if(a==3) //当a==3时 执行本else if后面语句 { printf("打球"); } else //else 输入a不为1,2,3时,执行后面语句 { printf("玩其他游戏"); } return 0; }
9.循环语句
while语句的一般形式为:
while(表达式) 语句
其中表达式是循环条件,语句为循环体。
while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体语句。其执行过程可用下图表示。
代码演示
#include<stdio.h>
int main()
{
int time = 0;
while(time<10000) //表达式,满足表达式则执行代码块的语句
{
printf("好好学习 ");
time ++; //限制循环条件,不限制循环条件会变成死循环 因为time永远等于0,
} //每一次加一,一万次后,time=10000,循环结束
return 0;
}
10.函数
在 C 语言中,函数由一个函数头和一个函数主体组成。下面列出一个函数的所有组成部分:
- **返回类型:**一个函数可以返回一个值。return_type 是函数返回的值的数据类型。有些函数执行所需的操作而不返回值,在这种情况下,return_type 是关键字 void。
- **函数名称:**这是函数的实际名称。函数名和参数列表一起构成了函数签名。
- **参数:**参数就像是占位符。当函数被调用时,您向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数可能不包含参数。
- **函数主体:**函数主体包含一组定义函数执行任务的语句。
简单理解函数用来使代码能有自己的功能,并实现功能性于单独性
例如:求两个数的较大值,我们如果有了该函数,直接调用就可以了,不需要重新写一遍。
#include<stdio.h>
int max(int num1, int num2) //返回的数据类型为 int,所以用int 类型接收
{ //接收的两个数据为int,故用两个int类型接收
/* 局部变量声明 */
int result = 0;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d%d",&a,&b);
int ret = max(a,b); //函数调用格式 函数名(); 这里将 a,b的值传过去。
printf("%d",ret);
}
结果很明显 如图
11.数组
要存储1-10的数字,怎么存储?
C语言中给了数组的定义:一组相同类型元素的集合
数组的定义
int arr[10]={1,2,3,4,5,6,7,8,9,10}; //定义int类型数组arr,[确定数组的大小],{放置数组元素};
数组的下标
C语言规定数组的每个元素都有一个下标,下标是从0开始的。
数组可以通过下标来访问的。
int arr[10]={1,2,3,4,5,6,7,8,9,10};
//数组有10个元素,下标是0-9;
数组的使用
打印数组。
#include<stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
while(i<10)
{
printf("%d",arr[i]); //打印1-10;
i++;
}
return 0;
}
当然,也可以用循环向数组中输入数值
#include<stdio.h>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i = 0;
while(i<10)
{
scanf("%d",&arr[i]); //输入1-10;
i++;
}
return 0;
}
12.操作符
简单介绍
-
算术操作符
* - + / %
数学的算术规则
-
移位操作符
>> <<
对一个数的二进制进行移位操作
-
位操作符
& ^ |
-
赋值操作符
= += -= *= /= &= ^= |= >>= <<=
相当于n = n(算术操作符)m
-
单目操作符
介绍前置++,后置++的区别
前置++,前-- 是先加再使用
后置++,后置–是先使用再加
x#include<stdio.h> int main() { int a = 10; int b = ++a; int c = a++; printf("%d %d",b,c); return 0; }
-
关系操作符
>
>=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
-
逻辑操作符
&& 逻辑与
|| 逻辑或
三目操作符
exp1 ? exp2 : exp3
逗号表达式
exp1, exp2, exp3, …expN
逗号表达式会按顺序执行
下标引用、函数调用和结构成员
[] () . ->
13常见关键字
13.1typedef
typedef 顾名思义是类型定义,这里应该理解为类型重命名。
#include<stdio.h>
typedef unsigned int uint_32;
int main()
{
unsigned int num1 = 0;
uint_32 num2 = 0;
return 0;
}
上述代码 将unsigned int 重命名为 uint_32;
num1与num2的数据类型是完全相同的
13.2 static
在C语言中:
static是用来修饰变量和函数的
- 修饰局部变量-静态局部变量
- 修饰全局变量-静态全局变量
- 修饰函数-静态函数
1.修饰局部变量
#include<stdio.h>
void test()
{
int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int c = 0;
while (c < 10)
{
test();
c++;
}
return 0;
}
结果明显由于每一次进入test函数
变量i都被赋值为0,并且函数运行结束以后,变量i都被销毁(生命周期结束)。
但是为变量 i 加上static后
会出现以下情况
#include<stdio.h>
void test()
{
static int i = 0;
i++;
printf("%d ", i);
}
int main()
{
int C = 0;
while (C < 10)
{
test();
C++;
}
return 0;
}
static将变量i变成了静态变量i,也就是说变量i的生命周期发生了改变,即便函数test运行结束,i也不会被销毁,i的值也不会发生变化,不会被重新赋值,达到了递增的效果
结论:
static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
2.修饰全局变量
add.c(另一个源文件)
int g_val = 2018;
test.c
#include<stdio.h>
extern int g_val; //声明
int main()
{
printf("%d\n", g_val);
return 0;
}
结果没有报错
也就是变量在同一个工程中,不同文件中的变量是具有链接属性的,只要声明,就可以在别的文件中使用
结果如图
用static修饰后
add.c(另一个源文件)
static int g_val = 2018;
test.c
#include<stdio.h>
extern int g_val; //声明
int main()
{
printf("%d\n", g_val);
return 0;
}
出现连接性错误
static修饰全局变量,让全局变量的外部链接属性变成了内部链接属性,从而使他的作用域由整个工程降级为整个文件,也就是作用域变小了,但是生命周期不变。
3.修饰函数
add.c (另一个源文件)
int add(int a ,int b)
{
return a+b;
}
test.c
#include<stdio.h>
extern int g_val; //声明
int main()
{
int a = 0;
int b = 0;
scanf("%d%d",&a,&b);
int ret = add(a,b);
printf("%d",ret);
return 0;
}
可以运行,函数也具有外部链接属性,可以在别的文件中调用函数
add.c (另一个源文件)
static int add(int a ,int b)
{
return a+b;
}
test.c
#include<stdio.h>
extern int g_val; //声明
int main()
{
int a = 0;
int b = 0;
scanf("%d%d",&a,&b);
int ret = add(a,b);
printf("%d",ret);
return 0;
}
该代码运行会出现以下报错
也就是说static修饰函数,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。其实就是函数失去了外部链接属性,变为内部链接属性
13.2 #define
#define MAX 100; //定义常量
#define add(x,y) ((x)+(y)) //定义宏
#include<stdio.h>
int main()
{
int a = 5;
int b = 6;
int ret = add(a,b)
//这时候的add(a,b) = ((a)+(b));
return 0;
}
14 指针
1 内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
看以下变量的地址
#include<stdio.h>
int main()
{
int a = 10;
printf("%p",&a);
//& 取地址操作符
//%p 是打印地址
return 0;
}
变量a是由4个地址的
打印出的只有一个地址,该地址是变量a的首地址。
利用指针变量操作存下a的地址
#include<stdio.h>
int main()
{
int a = 10;
int *p; //p是一个整形的指针变量
p=&a; //存下a的地址
return 0;
}
利用指针变量的解引用操作变量a
#include<stdio.h>
int main()
{
int a = 10;
int *p;
p=&a;
*P = 20;
return 0;
}
* 解引用操作符
这时候的*p代指的就是a,利用解引用,指针去操作变量a的值
指针变量的大小
#include<stdio.h>
int main()
{
printf("%d\n", sizeof(char *));
printf("%d\n", sizeof(int *));
printf("%d\n", sizeof(long *));
printf("%d\n", sizeof(double *));
return 0;
}
结果可以得出,指针变量的大小与数据类型无关,大小都是4个字节
注意:
指针大小在32位平台是4个字节,64位平台是8个字节。
15.结构体
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述人,人包含:名字+年龄+性别这几项信息。
这里只能使用结构体来描述了。
结构体的初始化
struct Stu
{ char name[20];//名字
int age; //年龄
char sex[5]; //性别
};
结构体的使用
struct Stu
{ char name[20];//名字
int age; //年龄
char sex[5]; //性别
};
#include<stdio.h>
int main()
{
//结构体信息
struct Stu s = {"张三", 20, "男"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s\n", s.name, s.age, s.sex,);
//->操作符 对指针变量结构体的使用
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s\n", ps->name, ps->age, ps->sex");
return 0;
}
16总结
在学习了基本的c语言语法知识,可这仅仅只是冰山一角,c语言是市面上几乎所有高级语言的鼻祖,其复杂性可想而知。希望未来再接再厉,继续深入学习c语言。与君共勉!