1.1 什么是C语言
1.1 .1计算机语言
------语言是人与人之间交流媒介
计算机语言的发展历程------机器语言->汇编语言->高级语言
(1. 面向过程:C 2. 面向对象:C++,JAVA,python,PHP······)
1.1.2 机器语言
机器语言:计算机是一种电子设备,计算机处理的数字信号是 0和1去记录相应信息,利用数字语言0和1来表示计算机能够识别的通断和断电两种状态。那么计算机的语言成为机器语言,自然也就是0和1序列,这种 0 和1 序列被称为二进制代码。
1.1.3 汇编语言
汇编语言:汇编的出现简化程序员的工作,在汇编语言中,用便于记忆的方法定义程序指令(用助记符代替机器码的指令集)。
1.1.4 高级语言
高级语言:既然机器语言和汇编语言都是计算机可以理解的语言,可用于完全控制计算机的行为,那为什么还会设计出并使用高级语言呢?因为机器语言和汇编语言都是低级语言,是面向于机器,于具体的计算机相关,学习器来非常困难,编程效率低,可读性,可操作,可维护性差。C语言作为面向过程的计算机编程语言,与C++,Java等面向对象的语言有所不同,其编译器主要有Clang、GCC、WIN-TC、MSVC、Turbo C等。
1.2. C语言的特点
C语言作为面向过程的计算机编程语言,属于高级语言范畴,它既有高级语言的特点,又有汇编语言特点。设计目标是提供一种能以简易方式编译、处理低级储存器的编程语言。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算硬件的应用程序,代码精简,十分灵活。
它把高级语言的基本结构和语与低级语言的实用性相结合,C语言可以像汇编语言一样对位,字节和地址进行操作,而这三者是计算机最基本的工作单元。
1.2.1 C语言程序的特点
1. C语言简洁,紧凑,使用方便,灵活;
2. 符丰富,共有34种;
3. 数据结构丰富;
4. 可移植性好(相对于汇编);
5. 生成目标代码质量高,程序执行效率高,C语言允许直接访问物理地址,能进行位(bit)操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作。
1.2.2 C语言程序的注意点
1. 一个C语言源程序可以由一个或多个源文件组成;
2. 每一个源文件可由一个或多个函数组成;
3. 一个源程序不论由多少个文件组成,都有一个且只能有一个main函数,即主函数。
(程序由主函数开始运行,主函数结束程序);
4. 源程序种可以有预处理命令(include 命令仅为其中一种),预处理命令通常应放在源文件或源程序的最前面(程序的编译从主文件的第一行开始,主函数结束编译结束);
5. 每一个说明,每一个语句都必须以分号结尾。有例外:预处理命令,函数头和花括号“}”之后不能加分号(一个分号代表了一个语句结束);
6. 标识符,关键字之间必须至少加一个空格以示间隔;
1.2.3 C语言程序的编程风格*
1. 一个说明或一个语句占一行。
2. 用{ }括起来的部分,通常表示了程序某一层次结构,{ }一般与该结构的第一个字母对齐,并单独占一行。
3. 低一层次的语句或说明可以高一层次的语句或说明缩进若干个后书写,以便看起来更加的清晰,增加程序的可读性。
总结:在编程应该遵循这个规定,以养成良好编程习惯和编程风格,好的代码风格要求缩进整齐,每一个语句一行,适当留空行。
1.3. C语言程序开发
1.3.1 第一个C语言程序
C语言项目由头文件.h和源文件.c组成,我们写的一般是源文件;
说明:1)#include <stdio.h>表示头文件包含,标准的输入输出头文件;
以#开头的行,通常是我们要调用系统库函数时,需要包含相应的头文件,预编译的意思是:以#include <stdio.h>为例,在程序编译之前将stdio.h文件的内容添加到程序(原样拷贝);
2)main-->主函数,每一个C语言程序有且仅有一个main函数,main前面的int表示该函数的返回值类型。主函数后面跟着{ },C语言的函数后面都要有一对{ };
3)在main函数的{ }内部的代码时函数体部分,其中printf 是一个函数调用,调用stdio 里面的库函数,用于输出数据;
4)return 0:表示程序的返回值,对应main前面的int。
注意:C语言是严格区分大小写的
#include "stdio.h"
/ *
# ------预编译符号
inlcude ------预编译命令
" " < > ------<>代表是系统提供的库 " "代表自定义的库
stdio ------标准输入输出库
.h ------头文件
main ------主函数
( ) ------包括的形参
printf ------输出函数,并在屏幕上打印对应内容
* /
代码示例:
#include "stdio.h"
int main()
{
printf("hello world!!")
return 0;
}
1. // 和 /*......*/(不支持嵌套,注意/*和*/的正确配对)
2. 注释的作用和好处:主要用于给读者提供说明,提高程序的可读性,C语言编译器会忽略掉所有的注释,将其视为空白。但我们要养成编码的同时随手写注释的好习惯。特别是程序比较复杂的,代码量比较大的程序,就越有必要写注释,方便他人理解代码,方便自己总结,检查与回顾。
1.3.2 C语言的开发过程
1. 编辑:使用文本编译工具录入程序代码,生成源程序*.c ,*.cpp;
2. 编译:语法分析差错,翻译生成目标程序 *.obj;
3. 链接:与其他目标程序或库链接装配,生成可以执行程序*.exe;
4. 执行:运行最终的可执行文件。
2.1 C语言进制数表示
2.1.1 二进制数、八进制数和十六进制数的表示
- 二进制:二进制由0和1两个数字组成,使用时必须以0b或0B开头,例如0b110;
- 八进制:八进制由0~7八个数字组成,使用时必须以0开头,例如015(十进制中的13)
- 十六进制:十六进制由数字0~9组成、字母A~F或a~f组成,使用时必须以0x或0X组成(不区分大小写)例如0X2A(十进制的42)
- 进制进位方式 逢十进一
2.1.2 进制之间的换算
十进制转二进制: 除二取余 余数反转
十进制转八进制: 除八取余 余数反转
十进制转十六进制: 除十六取余 余数取反
2.1.3 八四二一码
进制转换一般模式:任意进制先转换为二进制再去转其他进制;
举例:十六进制转十进制或八进制
0XEA--------11101010----128+64+32+0+8+0+2+0=234---- 16^1*14+16^0*10 = 234
0352---------011 101 010----128+64+32+0+8+0+2+0=234---8^2*3+8^1*5+8^0*2=234
2.2 C语言的数据类型
2.2.1 数据类型分类及取值范围
类型 | 类型说明符 | 字节数 | 取值数 |
字符型 | char | 1 | 0~256 |
基本整形 | int | 4 | -2147483648~2147483647 |
短整型 | short int | 2 | -32768~32767 |
长整型 | long int | 4 | -2147483648~2147483647 |
无符号整型 | unsigned int | 4 | 0~4294967295 |
无符号短整型 | unsigned short | 2 | 0~65535 |
无符号长整型 | unsigned long | 4 | 0~4294967295 |
单精度实型 | float | 4 | 3/4E-38~3/4E+38 |
双精度实型 | double | 8 | 1/7E-308~1/7E+308 |
注意:数据类型前可以加unsigned,则变成无符号数,不加是默认是signed(有符号数)
Char ---- 1个字节 ---- 8位 ---- 1111 1111---- 0~255 ---- 256个数表示范围应该是 0~2^8-1
Int ----- 4个字节 ---- 32 ---- 0~2^32-1
注意:在32位编译器下 int 为32位,在16位编译器下 int 为16位
2.2.3 数据类型转换
C语言的类型有很多,当不同数据类型之间进行混合运算的时候,可能会引起混乱,为此产生了一种转换机制(一种数据转换成另一种数据类型),若参加运算的数据类型不同时,就要先将其转换为相同类型,最后再运算;
转换的规则有两种:
1. 自动转换规则
float在进行运算的时候无论是否由double类型都会自行转换成double进行运算;
Char和short运算时都会自动转换位int运算;
2. 强制转换规则
将一种数据类型强制转换成另外一种数据类型;
C语言强转类型一般格式为:(类型说明符)表达式;
例子:(float)a 或者是(int)(x+y)
强制转换注意内容:
- 浮点型转整型的时候:将浮点型(单双精度)转换为整型的时候,会舍弃掉小数点后面的数字,只保留整数部分;
- 单双精度相互转换:double型转float型时,先截取双精度的前7位有效数字,然后赋值单精度类型的变量;
- 字符型和整型的相互转换: 将整形赋给字符型时,只将低8位的赋给字符,高位的全部舍弃;
- 无符号与有符号的相互转换:若占据同样长度存储单元的有符号,无符号整数相互转换时,是原样赋值,内部的存储方式不变,但外部值可能发生改变。
2.3 C语言基础
2.3.1标识符
C语言程序中需我们命名的对象,如:变量,符号常量,函数名,自定义数据类型名等;
C语言规定标识符只能由字母,数字和下划线组成;
- 其中第一个字符必须是字母或下划线;
- 不能是关键字;
- 严格区分大小写;
以下表示符是合法的: a ,x3,BOKK,_7,abc6.......
2.3.2 关键字
1.C语言预先定义的一些标识符,被C语言赋予特定含义的小写单词;见如下:
auto | break | case | char | const | continue | default | do |
double | else | enum | extern | float | for | goto | if |
int | long | register | return | short | signed | sizeof | static |
struct | switch | typedef | union | unsigned | void | volatile | while |
2.关键字及含义内容如下:
关键字 | 含义 | 关键字 | 含义 |
auto | 声明自动变量 | int | 声明整型变量或函数 |
break | 跳出当前循环 | long | 声明长整型变量或函数返回值类型 |
case | 开关语句分支 | register | 声明寄存器变量 |
char | 声明字符型变量或函数返回值类型 | return | 子程序返回语句(可带参数,也可不带参数) |
const | 声明只读变量 | short | 声明短整型变量或函数 |
continue | 结束当前循环,开始下一轮循环 | signed | 声明有符号类型变量或函数 |
default | 开关语句中的“默认”分支 | sizeof | 计算数据类型或变量长度(即所占字节数) |
do | 循环语句的循环体 | static | 声明静态变量 |
double | 声明双精度浮点型变量或函数返回值类型 | struct | 声明结构体类型 |
else | 条件语句否定分支(与 if 连用) | switch | 用于开关语句 |
enum | 声明枚举类型 | typedef | 用以给数据类型取别名 |
extern | 声明变量或函数是在其它文件或本文件的其他位置定义 | unsigned | 声明无符号类型变量或函数 |
float | 声明浮点型变量或函数返回值类型 | union | 声明共用体类型 |
for | 一种循环语句 | void | 声明函数无返回值或无参数,声明无类型指针 |
goto | 无条件跳转语句 | volatile | 说明变量在程序执行中可被隐含地改变 |
if | 条件语句 | while | 循环语句的循环条件 |
2.4 常量与变量
2.4.1变量
在程序的运行中,其值可以改变的量叫变量。
1. 变量在内存中占据一定的存储单元,用存放该变量的值,变量由变量类型,变量名,变量值组成:
(1)变量类型表示该变量用来存储什么类型的数据;
(2)变量名用来区分不同的变量;
(3)在变量的存储单元中存放的值为变量值;
2. 定义变量:变量类型 变量名 变量值
数据类型 变量名1 = 初始值1....数据类型 变量名N = 初始值N
举例:如--------int a = 10;
#include "stdio.h"
int main()
{
变量类型 变量名 变量值
int a = 10;
return 0;
}
3. 在使用一个变量之前,应注意----先定义 后使用
原因:定义变量是为变量指定数据类型,这个是编译就能在内存中分配相应存储单元。
4. 变量命名
- (1)只能由字母、数字、下划线组成,不能以数字开头;
- (2)变量名严格区分大小写;
- (3)变量名不能使用关键字;
- 5. 变量分类
- 局部变量:位于大括号内部定义的变量
- 全局变量:位于大括号外部定义的变量
-
#include "stdio.h" int a = 1010;//全局变量 { int b = 2020;//局部变量 return 0; }
注意:(1)局部变量可以和全局变量同名;
(2)当局部变量和全局变量同名时,局部变量优先使用,就实现了变量覆盖;
(3)局部变量的作用域是变量你所在的局部范围,全局变量的作用域是整个工程,不同源文件都可以使用。
6. 变量的作用域和生命周期
(1)作用域——一段程序代码中所用到的名字并不总是有效的/可用的,而限定这个名字的可用性代码范围就是这个名字的作用域;
- 局部变量的作用域是变量所在的局部范围
- 全局变量的作用域是整个工程
(2)生命周期——指变量的创建到变量的销毁之间的一个时间段;
- 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束
- 全局变量的生命周期是:整个程序的生命周期
2.4.2 指针变量
内存地址:在内存中以字节为单位存储数据,每一个字节有相对应值,这个值就是内存地址;
变量地址:变量在内存空间中所属的位置;
变量的内容:内存空间中存放的内容----也就是变量的值;
#include "stdio.h"
int main()
{
int dat = 30;
//变量存储时数值,但是它本身也有内存空间 内存空间=地址
//指针变量本质是地址 但是是变量,存储的是其他地址
int *sp = &dat;
printf("%d\r\n",dat);
printf("%d\r\n",&dat);
printf("%d\r\n",sp);
printf("%d\r\n",&sp);
}
2.4.3 常量
1. 定义:在程序运行过程中,其值不能被改变的量称之为常量。
常量同样对应着内存中的一块存储区域,通过常量名可以对其区域进行访问,和变量唯一不同之处在于便能改变常量的值。
2. 常量的前缀:(通常用来表示常量的进制:0表示八进制,0x十六进制)
常量后缀:(通常用来表示常量的类型:u表示无符号,l表示长类型,f表示浮点型,d表示double)
3. C语言中常量的分类:
- (1)字面常量
(2)const 修饰的常变量
(3)#define定义的标识符常量
(4)枚举常量
#include "stdio.h"
int main
{
3.14; //字面变量
"abc";//字面变量
const int a=10; //在C语言中,const修饰的是a,本质是变量,但是不能被修改,有常量的属性
a = 20;
printf("%d\n",a); //20 const 修饰的常变量
return 0;
}
#define max 10 //#define 定义的标识符常量
int main()
{
printf("%d\n",max);
return 0;
}
enum Color //枚举常量
{
RED; //枚举常量
GREEN;
BLUE;
}
int main()
{
printf("%d\n",RED);
printf("%d\n",GREEN);
printf("%d\n",BLUE);
return 0;
}
2.4.4 符号常量
定义:通常一个符号表示一个常量数据,常量名通常采用大写,符号常量可以用两种形式来定义
常量的定义格式:
1)宏:#define P1 3.14159265 这个语法是预编译指令语法,没有结尾
2)Const: Const float 3.14159265 这个语法是标准C语言常变量语法
2.4.5 直接常量
1. 整型变量:十进制整数常量------0~9-----逢十进一,整型变量默认是int类型;
2. 八进制整型变量:通常以0开头----0~7---逢八进一;
3. 十六进制整型变量:以0x开头----0~9,a~f---逢十六进一;
4. 浮点型变量:小数形式,是以十进制形式存在 比如:0.0 0.5 5.1等,浮点型默认是double类型的;
5. 指数形势(由十进制+阶码标志‘e’或‘E’),例如:1.2E3 =1.2*10^3;
6. 字符常量:字符常量使用一对单引号括起来的一个字符,例如‘a’,‘10’,‘+’;
2.5 字符串+转义字符+注释
2.5.1 字符串
1. 定义:由双引号引起来的一串字符称为字符串字面值,简称字符串,"abc"
注:字符串的结束标志是一个\0的转义字符,在计算字符串长度时,不作为字符串内容;
#inclde "stdio.h"
int main()
{
char arr1[]="abcd";
char arr2[]={'a','b','c','d','\0'};
printf("%s\n",arr1);
printf("%s\n",arr2);
printf("%d\n",strlen(arr1)); //字符串长度为4
//string length,求字符串长度的函数 头文件string.h
retuurn 0;
}
2.5.2 转义字符
定义:转变原来字符的意思,转义字符:用‘\’开头的字符序列(\n:换行)
字符串常量:用一对双引号括起来的字符序列,并且以‘\0’为结束标志,在内存中占的字节数为字符+1
转义字符 | 释义 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表示字符常量' |
\" | 用于表示一个字符串内的双引号 |
\\ | 用于表示一个反斜杠,防止他被解释为一个转移序列符 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3位的八进制数所代表的字符----例如\101------A |
\xdd | dd表示1~2位的十六进制数所代表的字符---例如\x42-----B |
//%d ——打印整型
//%c——打印字符
//%s——打印字符串,例如printf("%s\n","abcdef")
//%f——打印float类型的数据
//%lf——打印double类型的数据
2.5.3 注释
代码中有不需要的代码可以直接删除,也可以注释掉(加//);
代码中有些代码比较难懂,可加文字注释;
/* C语言的注释风格
int a = 10;
int b = 20;
*/
C++的注释风格
// int a = 10;
// int b = 20;
2.6 运算符与表达式
1. 运算符-------就是指具有运算意义的符号--- + - * /等;
2. 表达式-------指编译器能够读懂的计算机语句,由运算符和操作数按一定语法规则结合而成。
3. 按操作数的个数可以把运算符细分:
- 单目运算符(++,--)
- 双目运算符(+,-,*,/)
- 三目运算符(?:运算符)
通常又被分为:算术运算符,逻辑运算符,关系运算符,位运算符,条件运算,赋值运算符,逗号运算,sizeof运算符及其其他运算符。
2.6.1 算数运算符
1. 算术运算符有:加+ 减- 乘* 除/ 取余% 正负号(+ -) 自增(++) 自减(--);
2. 其中前面五个的运算符的结合性是从左到右 ,负号则相反从右到左。
注意:
- 在除法操作的时候,如果被除数和除数都为整型,那么结果一定是整型,舍去小数部分。在取余的操作时,只能用于整型数据;
- ++和--运算符:它们是单目运算符,结合性为从右到左边;
前缀----(++a,--a)表示先将a加上或减去1之后再赋值给左值;
后缀----(a++ , a--)表示先赋值给左值,a再加上或减去1;
2.6.2 逻辑运算符
1. 逻辑运算符有:逻辑与(&&) 逻辑或(| |) 逻辑非(!)
2. !是单目运算符,结合方向从右到左,&&和||为双目运算符,结合方向从左到右。逻辑运算符要求起操作数为布尔值: true 1 false 0
注意:由&&和||运算符组成的逻辑表达式中,C规定只能够确定整个表达式值所需要的最少数目的子表示进行计算,也就是说,当计算出一个子表示式的值后便可以确定整个逻辑表示式的值时,后面的子表达式就可以不需要在进行计算了,这种表达式也称之为短路表达式;
2.6.3 位运算符
存储单元内数据是由 0 和 1 组成,可以通过位运算符改变内存中某单元的某一值;
- 逻辑运算符:&(按位与),|(按位或),^ (按位异或),~(按位取反)左移<< 右移>>
- 按位与:&(有0出0,全1出1)0011&1111 = 0011
- 按位或:|(有1出1,全0出0)0011|1111 = 1111
- 按位异或:^(相同为0,不同为1)0011^1111 = 1100
- 按位取反:~ ~0011 = 1100
- 左移:<< 高位溢出丢弃,低位不足补0:0111001<<2 = 1100100
- 右移: >> 正数:高位补0,低位溢出舍去:0111001>>4 = 0000011 负数:高位补1,低位溢出舍去:11111111>>4 = 11111111
2.6.4 关系运算符(比较运算符)
1. 分类:大于(>) 小于(<) 小于等于(<=) 大于等于(>=) 判断等于(==) 不等于(!=)
2. 结合性:从左到右 ,主要用于程序中的分支判断并在变量和零值得比较应用最广泛
(1)整型变量是否为0:if(x==0)
(2)浮点型变量是否为0:if((x>=-0.0000001) &&(x<=0.0000001))
(3)布尔型得变量是否为0:if(x)
(4)指针类型得变量是否为0:if(x == NULL)
(5)字符类型得变量是否为0: if(x == ‘\0’)
3.1 C语言程序结构
九条语句:用来进行程序之间的逻辑设计;
选择:1.if - else 2.switch case default
循环:1.for 2.while 3.do.....while
跳转:1.goto 2.break 3.continue 4.return
3.2 选择结构基本语句
3.2.1 条件判断语句
(1)if语句:单条件判断语句
定义:当满足条件语句时执行{}内的执行语句,否则不执行{}内语句;
if(条件表达式)
{ //条件满足时
要执行的语句;
}
(2) if…else…语句:条件分支语句
定义:当满足条件语句是(条件语句结果非0)执行{ }内执行语句1,否则执行else 后的执行语句2;
if(条件表达式)
{ //条件满足时
要执行的语句;
}
else
{ //条件不满足时
要执行的语句;
}
(3)if…else if…else…语句:多条件分支语句
定义:当不满足条件1时,继续判断下一个条件语句,直到满足条件语句时,则执行当前{}内执行语句1,如果前面所有的条件都不满足时,则执行最后的else中的语句;
if(条件表达式1)
{ //满足条件表达式1
要执行的语句;
}
else if(条件表达式2)
{ //满足条件表达式2
要执行的语句;
}
else if(条件表达式3)
{ //满足条件表达式3
要执行的语句;
}
···
else
{ //所以条件都不满足时
要执行的语句;
}
(4)switch语句:开关语句,一般配合case关键字使用
-
定义:通过表达式得出数值,若得出的数值与下面case后得值对应,则执行相应得语句,若没有相应得数值则会执行最后的default后面的语句;
-
switch(表达式) { case 值1: //如果表达式的值等于1,则执行下面语句1 执行语句1; break; //如果没有break则不会跳出语句回一直往下执行 case 值2: //如果表达式的值等于1,则执行下面语句2 执行语句2; break; ··· case 值n: //如果表达式的值等于n,则执行下面语句n 执行语句n; break; default: //如果表达式中没有相对应的值时则执行语句n后跳出 执行语句n+1; break; //break可省略 }
3.2.2 循环结构基本语句
(1)for语句 -
-
for (表达式1;表达式2;表达式3)
(循环变量赋初值;循环体条件;循环变量增量)
{
执行语句;
}
代码示例:
#include "stdio.h"
int main()
{
int i = 0;
for(i=0;i<10;i++)
{
printf("%d只羊\r\n",i);
}
}
(2)while语句 条件循环语句,当满足循环条件的情况下循环执行
while(条件语句) //循环条件
{
执行语句;
}
代码示例:
#include "stdio.h"
int main()
{ //两种用法皆可
int i = 0; //int i = 10;
while(1) //while(i--)
{
printf("你好!\r\n");
}
}
(3)do while语句
与while循环的区别:do…while会先执行一遍循环体里面的语句,再进行条件判断,也就是说,do…while至少会执行一次循环体中的语句;
do
{
执行语句;
}while(条件语句); //循环条件
代码示例:
#include "stdio.h"
int main()
{
int i = 10;
do
{
printf("你好!\r\n");
}while(1)
} //do···while先执行后判断,while先判断后执行