本章节主要目的是基本了解C语言的基础知识,对C语言有一个大概的认识。
什么是C语言
在日常生活中,语言就是一种人与人之间沟通的工具,像汉语,英语,法语……等。而人与计算机之间交流沟通的工具则被称为计算机语言,像C/C++,Java,python…等等。
C语言作为一门通用的计算机编程语言,广泛地应用于底层开发。并不是说C语言不能做应用软件开发,比如早期QQ就是用C语言进行编写的。
简单介绍一下计算机语言的发展吧,在早期并不存在C语言 ,程序员写代码写出的都是类似 10100101010 等等的一系列二进制序列,在真正使用过程中是极其复杂。因此,渐渐的人们又创造出来用 助记符 来表示不同的二进制序列,例如用PLAY来表示1001,GAME来表示1100,因此就称这种用助记符写代码的方式为汇编语言。后来又发展出来B语言,再到如今的C语言。
一门语言的好坏以及它的流行程度往往取决于它是否有国际标准。C语言在流行起来后,又出现了C语言在各公司的兼容性问题,鉴于此,在二十世纪八十年代为了避免各开发商用的C语言语法产生差异,美国国家标准总局(ANSI)为C语言制定了一套完整的语法标准,称为 ANSI C。早期公布的 C89 和 C90 都是目前使用最多的标准,至于后来的C99,C11,C17等等并没有被业内广泛接受。
下来介绍下目前大家常用的几款编译器:
苹果公司的 Clang ,Linux系统下的 GCC , VS集成开发环境下的 MSVC 等等一系列编译器。
看到这里可能会有小伙伴有疑问,唉,C语言和编译器有什么关联吗?其实C语言虽然表面上看上去是一行行代码,这代码计算机可不认识,因此C语言本质还是得变成计算机可以识别的二进制指令,那么这里的编译器就起到了将程序员写的C语言代码转换成电脑可以识别的二进制指令的这样一个作用。
第一个C语言程序
main函数是程序的入口,C语言程序是从main函数的第一行开始执行的,在一个项目(工程)中可以有多个 .c 文件,但是在多个 .c 文件中main函数有且仅有一个。
#include<stdio.h>
int main() //int说明main函数执行后返回一个整型值
{
printf("hello world\n");
return 0;
}
//注意事项:代码中的符号均为英文符号!
基本步骤:
//1.写出main函数
//2.使用printf函数进行打印操作
// 由于printf是一个库函数,因此需要包含对应的头文件--stdio.h
//包含头文件
//按下Ctrl+F5,运行程序
数据类型
写代码是为了人们更加便利的生活,可以说程序离不开日常生活中的各种数据。而把数字、字母和文字输入计算机时,这就使得C语言必须通过一些基本的数据类型对输入的值进行区分和使用不同的数据,因此C语言为程序员提供了两大系列的多种数据类型,接下来我将列出两大数据类型:
- 整数类型
- 浮点数(小数)类型
编辑存在这么多的类型,其实是为了更加丰富的表达生活中的各种值。其中双精度浮点数精度比单精度浮点数更高。浮点数在内存中是无法精确保存的。那这些类型在电脑内存中各占多大一块空间呢,我们可以用sizeof来计算所占内存空间的大小:
我们可以看到执行结果分别是1,2,4,4,8,4,8,单位为 byte(字节)。 在计算机中存储单元的单位有 bit byte KB MB GB TB PB,那这些单位的到底是多大一块地方呢?我们知道计算机能够识别的是二进制的指令,二进制又是由0和1组成的,那计算机就规定了一个二进制位的大小为1 bit,同时规定了1 bit 是计算机存储数据的最小单位。
- 1 byte = 8 bit。
- 1 KB = 1024 byte
- 1 MB = 1024 KB
- 1 GB = 1024MB
- 1 TB = 1024GB
数据类型是用来创建变量的。
#include<stdio.h>
int main()
{
//创建一个字符型变量
char ch = 'h'; //char类型创建一个变量ch,给ch赋值为h。
printf("%c\n",ch);
//存放一个人的年龄-10岁
int age = 10; //int类型创建一个变量age,给age赋值为10。
printf("%d\n",age);
//存放一个人的薪资
float salary = 10000.0f; //float类型创建一个变量salary,给salary赋值为10000.0f。
printf("%.1f\n",salary);
printf("%f\n",salary);
//计算机默认将小数看作 double 类型,因此在使用 float 类型创建变量时通常在小数后增加 f 。
//存放一个人的账户余额
double money = 1126.5; //double类型创建一个变量money,给money赋值为1126.5。
printf("%.1lf\n",money);
printf("%lf\n",money);
return 0;
}
//%c - 用来打印字符
//%f - 是打印float类型的浮点数 加 .1 就是保留1位小数
//%lf - 打印double类型的浮点数
变量、常量
生活中的有些值是不变的(比如:性别,身份证号码,血型),有些值是可变的(比如:年龄,体重,薪资)
不变的值在C语言中用常量的概念来表示,变的值在C语言中用变量来表示。
定义变量的方法
#include<stdio.h>
int main()
{
//类型 变量名 = ***;
int num = 0; //初始化:创建变量的同时赋给其一个值
printf("%d\n",num);
long long ln = 1000;
printf("%d\n",ln);
double weight = 55.5;
printf("%lf\n",weight);
return 0;
}
变量的命名
- 只能由字母(包括大写和小写)、数字和下划线( _ )组成。
- 不能以数字开头。
- 长度不能超过63个字符。
- 变量名中区分大小写的。
- 变量名不能使用关键字。
这里建议大家在写代码过程中尽量根据功能来选择具有意义的名字。
变量的分类
- 局部变量
- 全局变量
区分方法:全局变量在大括号外定义,局部变量在大括号内定义。
#include<stdio.h>
int num2 = 1000; //全局变量
int main()
{
int num1 = 100; //局部变量
printf("%d\n", num1);
printf("%d\n", num2);
return 0;
}
当局部变量和全局变量同名冲突的情况下,局部变量优先使用,建议是尽量不要让变量名称相同,出现这种冲突。
变量的使用
变量的作用域和生命周期
全局变量的作用域是非常广的,甚至可以跨源文件进行使用,需要使用extern进行声明,extern 是用来声明外部符号的。
生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期。
常量
C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:
- 字面常量
- const 修饰的常变量
- #define 定义的标识符常量
- 枚举常量
字面常量:
const 修饰的常变量:
常变量:const仅仅在语法层面限制num不能被更改,但num本质上还是变量。
#define定义的标识符常量:
枚举常量:
枚举意思是指能一一列举,如:性别(男、女、保密),三原色(红色、绿色、蓝色),星期(1,2,3,4,5,6,星期日)。可以自己创建。默认常量对应的值是从0开始,也可自己修改。
字符串+转义字符+注释
字符串
在C语言中这种由双引号引起来的一串字符称为字符串字面值,简称字符串。
注意:字符串的结束标志是一个 ‘\0’ 的转义字符。在计算字符串长度的时候 ‘\0’ 是结束标志,不算作字符串内容。
%s是用来打印字符串直到 ‘\0’ 才终止打印。%c是用来打印字符
导致上图情况的原因是:arr2中存有’\0’也就是说有结束标志,所以打印出abc就结束了;而arr1中只有 ‘a’ ‘b’ ‘c’,剩下的元素不明确,因此计算机就随机打印出来一些字符直到打印到 ‘\0’ 为止。
知道真正的原因后,我们就可以很好的解决这个问题,那就是给arr2加上一个 ‘\0’ :
转义字符
转义字符 | 释义 |
---|---|
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\’ | 用于表示字符常量’ |
\“ | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 X |
\xdd | dd表示2个十六进制数字。 如: \x30 0 |
三字母词:旧的编译器会将 ??)识别为一个字符串,转换成 ] 。因此在旧的编译器上想要打印??)就需要换成 ??) 来达到效果。
八进制数字130转换为十进制数字后为88,ASCLL码为88的字符是’X’
八进制数字73转换为十进制数字后为59,ASCLL码为88的字符是’;’
十六进制数字35转换为十进制数字后为53,ASCLL码为88的字符是’5’
十六进制数字55转换为十进制数字后为85,ASCLL码为88的字符是U’
小练习
#include<stdio.h>
//计算下面程序的结果
int main()
{
printf("%d\n", strlen("abcdef"));
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}
注释
- 代码中有不需要的代码可以直接删除,也可以注释掉
- 代码中有些代码比较难懂,可以加一下注释文字
注释有两种风格:
- C语言风格的注释 /xxxxxx/ 缺陷:不能嵌套注释
- C++风格的注释 //xxxxxxxx 优点: 可以注释一行也可以注释多行,比较推荐
选择语句
过两天加
循环语句
过两天加
函数
过两天加
数组
过两天加
操作符
过两天加
常见关键字
C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。
关键字auto
局部变量的特点是:进入作用域自动创建,出了作用域自动销毁。因此局部变量又称为自动变量。
在起初创建一个局部变量时,其数据类型前是有 auto 的。
auto int a = 10;
关键字register
寄存器关键字只能建议将数据放在寄存器中。
register int num = 100;
关键字typedef
typedef 顾名思义是类型定义,这里应该理解为类型重命名,让复杂的类型简单化。
typedef unsigned int uint;
typedef struct Node
{
int data;
struct Node* next;
}Node;
int main()
{
unsigned int num = 100;
uint num2 = 200;
return 0;
}
关键字static
static是用来修饰变量和函数的:
- 修饰局部变量-称为静态局部变量
- 修饰全局变量-称为静态全局变量
- 修饰函数-称为静态函数
修饰局部变量:static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。
一个普通的局部变量是放在栈区的,而被static修饰的局部变量是放在内存的静态区的。因此static的本质是改变了存储位置。
修饰全局变量:全局变量是具有外部连接属性的,在其他源文件内部适当声明就可以使用,但是一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用。否则会在编译的时候出现连接性错误。
修饰函数:和修饰全局变量类似,一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用。在编译的时候会出现连接性错误。
define 定义常量和宏
定义常量:
定义宏:
指针
内存
内存是计算机上的一种存储空间,一般为16/8G。计算机中程序的运行都是在内存中进行的 ,程序如果有数据需要存储,也会申请内存空间。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1byte。
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
操作系统一般分为32位或64位,多少位就对应有多少根寻址线,以32位操作系统为例,它对应就有32根寻址线,每一根寻址线都可以通电,电又分为低频和高频,当某一跟线通的是高频时,这根线的二进制表示就是1,同理,通低频时,这根线的二进制表示就是0。
2的32次方对应的就是4G的大小,64次方对应的就是8G的大小
在计算机中我们喜欢使用十六进制来表示地址,一个十六进制位表示了4个二进制位。
变量是创建内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。取出变量地址如下:
如果我们想要存储一个地址,那就需要定义指针变量。
我们可以不直接对num进行修改,而是通过其地址p对num进行修改。
指针变量的大小
指针大小在X86(32位)平台是4个字节,X64(64位)平台是8个字节。
结构体
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。这就只能使用结构体来描述了。
在初始化结构体时,必须对应的是上边的结构体定义进行一一对应。