一、概述
C语言是一种计算机编程语言,我们是利用代码来控制计算机的运行,从而达到某种目的,我们就很有必要了解计算机的运行原理。
二、计算机
OS + 应用程序
1、计算机组成——硬件(Hardware)
基本组成 :
-
输入单元:输入数据给计算机处理,举例:键盘,鼠标;
-
输出单元:结果数据展示 ,举例:显示器,打印机;
-
外存储器:永久存放数据,容量大,但访问速率慢,举例:磁盘;
-
内存储器:临时存放待处理的数据及运行的程序代码,访问速度快,数据是临时存放,相对来说, 容量较小,举例:内存条;
-
中央处理单元(CPU):
-
运算器(ALU):进行算术运算和逻辑判断;
-
控制器(CU):管理和协调计算机的其它部件;
2、计算机运行原理
- 计算机通过输入设备将数据加载到内存;
- CPU从内存中获取数据进行处理,并将结果数据再次放回到内存;
- 通过输出设备将结果数据进行输出展示;
- 如果我们需要将结果数据进行长期存储,可借助于外存储器保存。
3、计算机语言
- 机器语言(0,1,指令码): 计算机唯一可以直接运行的代码;
- 汇编语言(符号化指令):汇编语言必须经过汇编程序转换为机器语言后计算机才能运行;
- 高级语言:利用数学运算符及一些英文单词来描述程序指令。(C/C++/JAVA/Python)高级语言是必须要通过编译器或者解释器转换为机器语言。
三、C语言
1、C语言版本
为了C语言健康发展下去,很多有识之士及美国国家标准协会(ANSI)于1982年成立了一个委员会以 确定C语言的标准。
C89:1989 ANSI 发布了第一个完整的C语言标准,即C89;
C90:不过人们习惯性的称为 “ANSI C”1990年ISO(国际标准化组织一字不改的采纳了 C89,官方给出的 名称为 ISO C90) ;
C99:1999年,C语言标准经过了一次修正和完善后,ISO发布了新版的C语言标准,简称” C99”;
C18:最新的C语言标准为 2018年6月份发布的 “C18”。
2、C语言特点
(1) C语言是一种强大而灵活的语言,可以用来编写任意复杂的程序;
(2) C语言简洁、紧凑,使用方便;
(3) C语言是可移植的;
(4) C语言很适合结构化程序设计,因而要求用户以功能模块的方式来思考问题;
(5) C语言可直接控制硬件 ( 位运算符,地址 ) ;
(6) 生成目标代码质量高,程序执行效率高,运行速度快。
-
优点 :
- 功能强大,语言灵活;
- C可移植性强;
- C语言可以直接控制硬件;
- C语言运行效率高;
- C语言具有结构化的控制语句;
- C语言具有丰富的数据类型和运算符;
-
缺点 :
- C语言的缺点主要表现为数据的封装性弱。这一点使得C在数据的安全性上有很大的缺陷,这也是C和C++的一大区别;
- C语言的语法限制不太严格,对变量的类型约束不严格,影响程序的安全性,对数组下标越界不做 检查等。从应用的角度,C语言笔其他高级语言较难掌握。也就是说,对用C语言的人,要求对程序设计更熟练一些。
3、C语言开发过程
C语言的开发分为三步:①编辑 --> ②编译 --> ③运行;
- 创建一个C语言源程序文件(.c);
- 在源文件中由程序员编写C语言程序代码;
- 由编译器对源文件进行编译,生成可执行程序;
- 机器运行可执行程序,确认功能的正确性。
C语言的编译四步骤:①预处理 --> ②编译 --> ③汇编 --> ④链接;
4、C语言程序的基本结构
(1)一个简单的C程序
说明:
- 注释:增加程序的可读性,不被执行,主要是对代码进行解释说明,举例:// 向控制台输出一句话;
- 预处理命令: 程序中包含某一文件内容。 “stdio.h”为标准输入输出函数头文件名,举例: #include <stdio.h>;
- 主函数:C程序由函数组成。一个C程序有且仅有一个主函数,举例:int main(..) {..};
- 函数头:函数说明,说明函数类型、函数名和函数参数,举例:int main(..);
- 函数体:包括变量说明和语句执行部分,举例:{..};
- 函数调用语句:格式输出函数printf( ), 输出“hi shenyuanli!”,举例:printf("hello world!\n");
1.注释
概念:对代码增加解释说明性文字,这个文字可以提高代码的可读性,注释不会被编译和执行。注释 也可以屏蔽掉不执行但又不想删除的代码;
分类 :
- 单行注释:一般用于变量,语法如下:
//单行注释 int num = 12;
- 多行注释:一般用于函数,语法如下:
/* 多行注释 */ int main() { ... }
- 文档注释:一般用于函数、结构体、类等等,这个是多行注释的一种扩展写法,本质上还是多行注释;
/** * 文档注释 * @params 参数说明 * @author 编写者 * @date 编写日期 * @return 返回类型 */ int main() { ... }
5、C语言的规范
- 左右 { } 要独立一行;
- 左 { 的下一行代码必须要换行和缩进(一个tab键,或者偶数个空格);
- 右 } 和它所匹配的左 { 要垂直对齐;
- 代码要添加必要的注释;
- 函数之间最少留一行空行;代码中的不同部分建议也要加空行,相同部分代码建议写到一起;
- 命名要见名知意
//下面哪些命名是合理的,哪些命名是不合理的
aaa(),get_name(),set_name(),total(),123(),
6、标识符
-
什么是标识符:比如说变量名,函数名,数组名,结构体名字等等;
- 组成:数字,英文字母大小写,下划线_ , $ ;
-
注意事项:
- 不能以数字开头;
- 不能是关键字(如:int,double,main,include,stdio,if,for...)。
7、命名规范
1.起名字要见名知意,建议是简单的英文单词或被公认的一些缩写;
2.变量名,函数名 --- 小驼峰命名或者下划线命名:
- 小驼峰命名法:如果只有一个单词,全部小写;如果超过两个单词,从第二个单词开始,首字 母均大写,举例:getAge() | userId,Java或者C++ 推荐这种写法;
- 下划线命名法:如果只有一个单词,全部小写;如果超过两个单词,单词与单词之间使用"_"进 行分隔,举例: get_age() | user_id,C语言推荐这种写法;
3.结构体名,共用体 --- 大驼峰命名法:
- 大驼峰命名法:要求每个单词的首字母都大写,举例:GetName,Student,Person...
4.枚举常量、自定义常量(宏符号):每个字母都大写,多个单词之间可以用"_"分隔,举例: CLASS_NAME。
四、C语言进阶
1、数据类型
整型:
short(短整型):2个字节(16个bit位);
int(基本整型):4个字节(32个bit位);
long(长整型):4个字节(32个bit位)。
浮点型:
float(单精度型):4个字节(32个bit位);
double(双精度型):8个字节(64个bit位).
(1)基本类型
1.数值类型
A.整型
a.短整型:short;
b.整型:int;
c.长整型:long;
d.长长整型:long long;
B.浮点型
a.单精度:float;
b.双精度:doouble;
2.字符类型:char;
(2)自定义/构造类型【后续学习】;
1.结构体:struct;
2.共用体:union;
3.枚举:enum;
(3)指针类型【后续学习】;
(4)空类型:void;
2、常量与变量
在C语言中的表现形式是常量与变量。
(1)常量
常量:在程序执行过程当中其值不能改变的量称之为常量。
1.数值常量
整数常量
- 二进制常量:以0b开头,由0,1两个数字构成,举例: 0b1111、0b0110、0b01110101;
- 八进制常量:以0开头,由0~7八个数字构成,举例: 012345、07654 -075;
- 十进制常量:默认,由0~9共十个数字构成,举例: 1234、9876、-87654;
- 十六进制常量:以0x开头,由0~9,A-F共16个字符构成,一般用于嵌入式开发,举例: 0xFFFFFF、0xFFFF00
小数常量
- 单精度:常常给单精度的数值后加F作为标记,举例: 12.24F、-45.4444F;
- 双精度:默认就是双精度,举例:12.24、-45.4444;
2.字符常量
用单引号 ' ' 引起来的单个字符
举例: 'a' '1'
注意: 'a' - 字符, '马' - 错误
转义符:
' \n ' :换行符
' \t ' :制表符
' \\ ' :反斜线, \
' \0 ' :0字符对应的ASCII码值是0
3.符号常量
使用 #define 定义的宏
举例:
定义
-#define PI 3.1415926
定义 π,使用- 2 * PI
案例:
4.字符串常量
使用 "..." 引起来的字符序列,称之为字符串常量
注意 :C语言常量是支持字符串的,C语言变量不支持字符串(需要字符数组或者字符指针进行模拟)
系统自动为字符串常量加上结尾符 “ \0 ” ,使所占内存单元多一个,但字符串常量的长度不变,可用 sizeof( )运算符来测量。
举例 : printf("Hello World!")、printf("")、printf(1)-数值常量、printf("1")-字符串常量
案例 :
5.空常量
用于给指针变量作为默认值初始化:int *p = NULL;
注意 : * 前面是常量或者变量,此时 * 是数学运算符乘号, * 前面是数据类型,此时 * 表示指针;
补充:
长整型一般在数值后加 L 或者 l ;长长整型一般在数值后加 LL 或者 ll
long a = 90L;
long long b = 99LL;
练习题
(2)变量
说明:
-
表面:在程序执行过程中取值可以改变的数据称之为变量;
-
实质:变量其实代表了一块内存区域/单元/空间。变量名可视为该区域的标识。
-
整个变量分为三部分:
1.变量名:这个只是变量的一个标识,我们借助变量名来存储数据;
2.变量空间/内存单元:这个就是内存中分配的一块用来存储数据的空间/区域;
3.数据/变量值:这个就是存放在变量空间中的数据;
注意:我们把数据存放在变量名对应空间的过程称之为变量的赋值操作。
-
变量是内存中一块用来存储数据的空间;
-
变量由变量名+变量值构成。通过变量名可以存放和获取变量值。
变量定义格式
[标识符] 变量数据类型 变量名列表;
变量名的命名要符合下列两个规则:
- 变量名可以以数字、字母(区分大小写)、下划线_、¥组成,后面可以跟若干个字母、数字或下划线,不能以数字开头。如:max_width;
- 不建议使用中文,也不建议使用拼音;
- 变量名不能与C语言中已经存在的标识符重名,也就是关键字和保留字不能作为变量名(例如int,signed,if,break...)。
举例:
// 方式①:声明变量并赋值 (声明一块变量存储单元,并向这个空间存储一个初始值)
//注意:赋值操作顺序为 从右至左
int num1;
num1 = 21; //将21赋值给变量num1,也就是将21赋值给变量num1对应的内存单元
printf("%d",num1);//将num1对应的数据输出到控制台,需要指明输出数据的格式:int使用占位符%d表示
// 方式②:声明并赋初值(声明一块变量,暂时为空)
int num2 = 21;//这句代码执行:①向内存申请了一块存储单元(分配内存);②将21赋给num2对应的存储单元
printf("%d",num2);
//方式②:覆盖初始值
int num3 = 21;
num3 = 22;
printf("%d",num3);
//方式③:变量列表。逗号在C语言中可作为分隔符和运算符使用
int x = 12,y = 13;
说明:
1.变量定义是,利用同一个类型标识符可同时定义多个变量,各个变量之间使用 ","(英文逗号)分割;
2.定义变量后,如果未对变量进行初值的赋予,则变量所代表的内存空间中的数据是随机安排的;
3.可以在变量定义的同时给变量赋值,这个操作成为变量的初始化,C语言允许对变量进行初始化;
4.初始化变量是,尽量做到类型相同,举例:long l = 567L;
5.整形数据在内存中的存放方式:
按照补码方式存放:
- 正整数的补码就是将该数据转换为为二进制格式;
- 负整数的补码就是将该数据的绝对值转换为二进制格式,按位取反,并+1。
6.浮点型数据在内存中的存放方式:
按照指数方式存放:
类型 | 符号位 | 指数位 | 尾数位/部分(小数) | 指数偏移量 |
---|---|---|---|---|
float(4个字节) | 1位[31] | 8位[30-23] | 23位[22-00] | 127 |
double(8个字节) | 1位[63] | 11位[62-52] | 52位[51-00] | 1023 |
举例:
需求:将 27.5 以 float 类型存放;
解析:
- 27.5的二进制为11011.1,指数表示法:1.10111*2⁴
-
指数:4,加上127,就是131,二进制1000 0011
-
尾数(小数点后的数)10111,补够23位 1011 1000 0000 0000 0000 000
-
用二进制表示就是 (符号数位1位)0 (指数位8位)1000 0011 (尾数位23位)1011 1000 0000 0000 0000 000
-
所以,单精度浮点型数据27.5在内存中的存储方式如下 0 1000 0011 1011 1000 0000 0000 0000 0000
注意:浮点型数据在内存中存放的是一个近似值。
7.字符数据在内存中的存放方式:以ASCII码存放。
字符的存在分为两种形式,ASCII码(编号,从0开始的正整数)和ASCII码值(数据,包括英文字母大小写、数字、特殊符号)。
注意:ASCII码是可以和整数进行数学运算的。
举例:
//写法1
char c1 = 'A';
//写法2
char c2 = 60;
字符型数据和整型数据之间可以通用。即一个字符数据既可以字符形式输出,也可以整数形式输出。
1、以字符形式输出时,系统先将内存单元中的ASCII码转换成相应字符,然后输出;
2、以整数形式输出时,直接将ASCII码作为整数输出;
所以可以对字符数据进行算术运算,这时相当于对其ASCII码进行算术运算。
%c 输出字符形式; %d 输出整数形式
注意:字符数据只占一个字节,只能存放0~255范围内的整数。
-
每一个英文小写字母都比它相应的大写字母的ASCII码大32
-
char类型的ASCII码值(就是整数)与int型进行转换;
-
转换成整数型和字符型
-
超出存放范围
3、数据类型之间的转换
规则:不同的数据类型参与运算,需要转换为同一类型后运算
数值比较由小到大简单排序:
short < char < int < long < float < double
-
隐式类型转换
说明:编译系统自动完成,一般是低优先级类型向高优先级类型转换,这种被称为自动类型转换(由小到大)。
语法:
大数据类型 变量 = 小数据类型变量;
举例:
//案例1
char c = 'A';//65
int num = c;
printf("%d",num);//65
//案例2
char c2 = 'A';//65
int num2 = c2 +22;
printf("%d",num2);//87
-
强制类型转换
说明:程序员自己实现,一般是高优先级类型向低优先级类型转换,这种被称作强制类型转换(由大到小)。
语法:
小数据类型 变量名 = (小数据类型)大数据类型变量
举例:
//案例1
int num1 = 65;
char c1 = (char)num1;
printf("%c",c1);// A
//案例2
int num2 = 65;
char c2 = (char)(num2 + 32);// char不是函数
printf("%c",c2);// a
注意:强制类型转换过程中,可能会出现精度缺失的问题。如果大类型数据范围 <= 小类型数据范围,此时数据不会丢失,正常转换;如果大类型数据范围 > 小类型数据范围,此时丢失超出部分的数据,精度会缺失!
原则:类型转换并不会改变原变量本身的类型。
变量名、变量值、变量所占存储单元之间的关系
注意:在C语言中,要求对所用到的变量使用前必须先强制定义,即:先定义,后使用。
4、运算符
(1)算术运算符
单目运算符
说明:++ -- +(正) -(负) *(解引用)
++a 与 a++ 的区别:
- int a = 1,int x = ++a; ++在前,先自加1,后运算(先计算,再赋值);
- int a = 1,int x = a++; ++在后,先运算,后自加1(先赋值,再计算);
举例:
总结:
不管是 ++ 在前,还是 ++ 在后,计算数自身都会+1。区别在于运算的结果不一样。
练习:
int i = 5; 如果 int ret1 = i+++i++;//求ret1和i的值 如果 int ret2 = i+++(++i);//求ret2和i的值
--a 和 a-- 的区别
- int a = 1,int x = --a; -- 在前,先自减1,后运算(先计算,再赋值);
- int a = 1,int x = a--; -- 在后,先运算,后自减1(先赋值,再计算)。
双目运算符
说明:+ - * / %
举例:
#include <stdio.h>
int main()
{
printf(3/2);// 结果是1 ①为什么结果是1而不是1.5?因为是整型的运算,会直接舍弃掉小数部分
printf(3*1.0/2);// 结果是1.5 ②为什么结果是1.5而不是1?3*1.0=3.0(1.0是double类型,将结果从整形转换为double类型)
printf(10%3);// 结果是1 ③求模运算
printf(10.0%3);// 结果是error ④求模运算是针对整数进行的
int a = 10;
printf(a*1.0);
return 0;
}
注意:
- 两个整数相除的结果是整数,小数部分被舍弃。要想其结果是实数,可在分子*1.0(隐式类型转换);
- 求模运算(取余运算)左右两边的操作数都必须是整型。如果是类似于3.0这样的数,是错误的。
关系运算符
说明: > < >= <= \
举例:
什么是表达式(变量 + 运算符 组成表达式)?
表达式就是表达某种意思的式子。在C语言中,表达式指的是 运算符 连接 操作数 (变量|常量
...)的式子。
注意:
由关系运算符构成的表达式称为关系表达式,关系表达式的值为boolean(布尔值)
- 非0:关系成立,为真;
- 0:关系不成立,为假。
逻辑运算符
说明:&&(与) ||(或) !(非)
- &&:逻辑与(且),符号两边的操作数都为真,结果才为真,举例:((5>4)&&(5-4)>1),结果为假;
- ||:逻辑或(或),符号两边的操作数只要有一个为真,结果就为真,举例:((5>4)||(5-4)>1),结果为真;
- !:逻辑反(取反),取反,非0为真,举例: !(!(5>4)),结果为真;
惰性运算:
所谓的惰性运算,就是减少运算次数。
- 短路与:&&两边的操作数,只要左边不成立0,直接返回假,不再检验右边;
- 短路或:||两边的操作数,只要左边成立1,直接返回真,不再检验右边。
注意:
算术运算符,运算结果是数值类型;
关系运算符,运算结果是boolean类型(其实就是int的 0-假 ,非0-真);
逻辑运算符,运算结果是boolean类型(其实就是int的 0-假 ,非0-真)。
(2)位运算符
说明:按位(bit)来进行运算操作的运算符。
语法:~ & | … ^ << >>
~ :按位取反
说明:单目运算符,数据的每一个bit位取反,也就是二进制数位上的1变0,0变1。
举例:
unsigned char ret = ~0x05;//对 十六进制 的 5 转化为二进制 进行 按位取反
// 0000 0101 --> 1111 1010
printf("%d\n",~5);//对 十进制 的 5 转化为二进制 进行 按位取反
// 0000 0101 --> 1111 1010
& :按位与
语法:a & b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位对齐,处理结果如下:
- 1 & 1:1 1 & 0:0 0 & 1:0 0 & 0:0
总结:如果我们前后两个操作数对其位置上的二进制数字都为1,其结果是1,否则结果均为0;
| :按位或
语法:a | b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位对齐,处理结果如下:
- 1 | 1:1 1 | 0:1 0 | 1:1 0 | 0:0
总结:如果我们前后两个操作数对其位置上的二进制数字只要有1,其结果是1,否则结果为0;
^ :按位异或
语法:a ^ b
说明:首先将参与计算的操作数转换为二进制,然后按照每一位对齐,处理结果如下:
- 1 ^ 1:0 0 ^ 0:0 1 ^ 0:1 0 ^ 1:1
总结:如果我们前后两个操作数对其位置上的二进制数字不同,其结果为1,否则结果为0;
<< :左移,按bit位往左偏移(数值会变大)
1.无符号左移:
语法:操作数 << 移动位数(bit位)
unsigned int a = 3 << 3;//将 3 转化为 二进制 后 向左移动 3位
printf("%d\n",a);// 24
2.有符号左移:
语法:操作数 << 移动位数(bit位)
unsigned int a = -3 << 3;//将 3 转化为 二进制 后 向左移动 3位
printf("%d\n",a);// -24
>> :右移,按bit位往右偏移(数值会变大)
1.无符号右移:
语法:操作数 >> 移动位数(bit位)
unsigned int a = 3 >> 3;//将 3 转化为 二进制 后 向右移动 3位
printf("%d\n",a);
2.有符号右移:
语法:操作数 >> 移动位数(bit位)
unsigned int a = -3 >> 3;//将 3 转化为 二进制 后 向右移动 3位
printf("%d\n",a);
举例:
注意:
1.在进行移位运算的时候,凡是被移出去的位统统丢弃,凡是空出来的位统统补0.移位运算针对的是无符号整数;
2.如果非要进行有符号的移位运算,那么左移的时候,空出来的补0,右移的时候,空出来的补符号位(原码阶段);
(3)其他运算符
说明:= += -= *= /= %=
赋值运算符
包含:= ,由 右 -> 左,优先级排倒数第二。
int a = 4;
int num = 5 + 6;
注意:
赋值运算符的左边(左操作数)必须是可写的地址。
复合赋值运算符
包含:+= -= *= /= %= ,由 右 -> 左,优先级排倒数第二。
int i = 1;
i+=1;//等价于 i = i + 1
i*=5;//等价于 i = i * 5
三目运算符
语法:表达式1 ? 表达式2 : 表达式3
求值顺序:
- 如果表达式1的值为1(真),则整个条件运算表达式的值为表达式2的值;
- 如果表达式1的值为0(假),则整个条件运算表达式的值为表达式3的值;
//案例1 //需求:根据考试成绩进行奖励和惩罚 // score >= 90 奖励外星人电脑一台 // score < 90 奖励刷锅刷碗1个月 int score = 89; printf("%s",score >= 90 ?"奖励外星人电脑一台":"奖励刷锅刷碗1个月");//奖励刷锅刷碗1个月 %s 字符串 //案例2 int a = 10,b = 20; int ret = a>b?++a:++b; printf("ret:%d a:%d b:%d",ret,a,b);// ret=21,a=10,b=21
练习题:
使用三目运算符比较三个任意整型数的最大值?
sizeof(int)
说明:用来计算某种类型或者变量所占的字节数。(中文英文字符集问题,不标准)
逗号运算符(,)
说明:优先级最低,左 -> 右,由多个运算符将多个不同的式子连接起来的表达式称之为逗号表达式;
语法:
(表达式1,表达式2,...,表达式n);
求值顺序:先求表达式1,再求表达式2,以此类推,整个逗号表达式的值为表达式n的值。
注意:
- 逗号表达式的优先级最低;
- 运算顺序从左往右;
- 整个逗号表达式的值取决于最右边的表达式的值。
举例:
int a = 5,b = 3;
int ret = (a>b,a++,b++,a);(这种写法其实就是为了减少代码量)
printf("ret:%d\n",ret);
五、扩展:
ISO-8859-1:西欧编码,一般遇到直接改编码;
GBK:国标,中国标准编码/字符库,收录了大量的汉字+中文符号;
UTF-8:全球标准,几乎收录了全球的各种字符集,包括GBK包含的常用汉字以及中文符号;
ASCII:字符集,C语言字符就是以ASCII码进行存储。针对程序内部数据。
1、常见的字符编码
- ASCII:1个字符等于1个字节,总共256个字符,针对程序内部;
- GBK:1个字符等于2个字节,表示简体、繁体及其符号。表示: \xced2;
- Unicode:四个字节表示:全球统一 编码,囊括了全世界所有的字符。表示: \u6211;
- UTF-8:长度变化的字符集,是对Unicode字符集的优化,提高效率,表示: \xe68891;
- ISO-8859-1:这个是西欧语言字符集。
如果代码中有字符乱码----编码和解码的字符集不一致:
解决方案:
- 修改成一致的编码;
- 换成英文或者数字,毕竟只有中文才会乱码
2、进制转换
int 4字节(8位)
float 4字节
double 8字节
我们目前接触到的进制有二进制、八进制、十进制、十六进制
1.十进制整型常量:由0至9的数字组成,没有前缀,不能以0 开头;
2.八进制整型常量:以0(数字0)为前缀,其后由0到7的数字组成,没有小数部分;
3.十六进制整型常量:以0x或0X为前缀,其后由0到9的数字和A到F(大小写均可)字母组成,没有小数部分;
整型常量中的长整型数据可用L作后缀表示。如:1234L等。
-
其他进制 转 十进制:
按权相加
- (1234)⏨ = 4*10⁰ + 3*10¹+2*10²+1*10³
- (0*1234)₁₆ = 4*16⁰+3*16¹+2*16²+1*16³
-
十进制 转 其他进制:
辗转相除法:将需要转换的数据不停的除以转换的进制数,直到商为0;
1.十进制转二进制
2.十进制转八进制
-
八进制 转 十六进制:
借助于二进制,将八进制转化为二进制,将二进制转化为十六进制;
-
十六进制 转 八进制:
借助于二进制,将十六进制转化为二进制,将二进制转化为八进制;
3、有符号数和无符号数
在C语言中,整数是可以带符号的(有符号,signed)或不带符号的(无符号,unsigned)。这两种类型的整数在内存中以二进制形式表示,并使用不同的模式。
-
有符号数(Signed Numbers)
有符号数是来表示正数、负数、0的整数类型;
在内存中,有符号数使用最高位(通常是符号位)来表示正负;
如果最高位为0,表示这个数是正数或0;如果最高位为1,表示这个数是负数;其余位用于表示数值本身。
举例:例如一个8位有符号整数可以表示的范围是 -128 ~ 127 。这是因为1位用于表示符号(正或负),剩下的7位。
注意:有符号位是默认的,在C语言中,基本整数类型如 int,short,long 默认为有符号数,除非明确指定位无符号。
举例:
signed int num = 12; //标准有符号位写法
int num == 12; //默认省略signed关键字
-
无符号数(Unsigned Numbers)
无符号数是只能表示非负整数的数据类型。在内存中,无符号数不使用符号位,所有位都用于表示数值。因为,无符号数的范围比有符号数的范围更大。
注意:在C语言中,通过关键字后天添加 unsigned 。来指定无符号类型,如 unsigned int、unsigned short...
举例:例如一个8位的无符号整数可以表示的范围是 0 ~ 255 。这是因为所有8位都用来表示数值,没有符号位。
unsigned int num = 12; //标准无符号位写法
4、原码、反码和补码
计算机存储的是补码。
原码:是最直观的表示方法,它直接用二进制数表示一个数,包括正负号。在原码中,最高位(最左边的位)是符号位,0 表示正数,1 表示负数;其余位表示数值本身。例如,十进制数 +5 的原码表示为 0000 0101
,而 -5 的原码表示为 1000 0101
;
反码:主要用于表示负数。对于正数,其反码与其原码相同。对于负数,其反码是将原码除符号位外的所有位取反(0 变 1,1 变 0)。例如,十进制数-5的反码表示为1111 1010;
补码:是计算机中最常用的表示方法,用于进行二进制加法运算。对于正数,其补码与其原码相同。对于负数,其补码是其反码加 1。补码的一个重要特性是,任何数的补码加上该数本身,结果总是 0。例如,十进制数 -5 的补码表示为 1111 1011
。
0的反码、补码都为0。
六、标识符
1、关键字(32个)
数据关键字(12个):char ,double ,float ,enum ,unsigned ,int ,long ,short ,signed ,struct ,union ,void ;
控制语句关键字(12个):for ,do ,while ,break ,continue ,if ,else ,goto ,switch ,case ,default ,return ;
存储类型关键字(4个):auto ,extern ,regsiter ,static ;
其他关键字(4个):const ,sizeof ,typedef ,volatile ;
2、预处理命令(12个)
define endif elif error line include
ifdef ifndef pragma undef if else
七、C语言程序设计结构
C语言的核心(灵魂)
数据结构 + 算法 = 程序
- 对数据的描述:数据结构;
- 对于问题解决的操作步骤的描述:算法
算法的特征:
- 有穷性;包含有限的操作步骤,不能无限制地执行下去;
-
可行性;算法中的每一条指令必须是切实可执行的;
-
确定性;算法中的每一条指令必须有确切的含义,不能产生歧义。
1、算法的描述:流程图
ANSI规定了常用的流程图符号
2、C语言程序设计的设计结构
三大结构: 顺序结构、分支(选择)结构、循环结构
顺序结构:
说明:各操作是按先后顺序执行的。是最简单的一种基本结构,也是默认的结构。
流程图:
选择结构:
说明:又称分支结构。根据是否满足给定条件而从两组操作中选择执行一种操作。
流程图:
循环结构:
说明:又称重复结构,即在一定条件下,反复执行某一部分的操作。
-
当型循环
流程图:
特点:
先判断,后执行,S有可能一次也不执行。
-
直到型循环
流程图:
特点:
先执行,后判断,S最少要执行一次。
3、C语句概述
C程序结构:
C语句的分类:
1.控制语句:用于完成一定的控制功能
- 控制语句:while.. for.. if..else... ...
- 函数调用语句:scanf(...);
- 表达式语句:b=3;
- 空语句:;
- 复合语句:{...}
① if ( ) …… else ……
② for ( ) ……
③ while ( ) ……
④ do …… while ( )
⑤ continue【跳过本次循环】
⑥ break【跳出后续所有循环,循环结束】
⑦ switch ( )
⑧ return
⑨ goto 标号 (无条件跳转语句)
说明:“( ) ”中是一个判断条件, “……”表示内嵌的语句。
2.函数调用语句:由一个函数调用加一个分号构成,例如: printf(“This is a C statement.”);
3.表达式语句 由一个表达式加一个分号构成,最典型的是赋值语句;
例如:
a=3; 是一个表达式
八、输入输出缓冲机制
1、概述
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间, 这些存储空间用来缓冲输入 或者输出的数据,这部分预留的空间叫做缓冲区。缓冲区根据其对应的是 输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
2、为什么要有缓冲区?
- 减少IO设备的操作;
- 提高计算机的运行速度。
比如:我们从磁盘里读取信息,先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓 冲区的数据取完后再去磁盘中读取,这样就减少磁盘的读写次数,再加上计算机对缓冲区的操作大大 快于磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
3、缓冲区的类型
- 全缓冲:当填满缓冲区之后,才会进行实际IO操作。 比如 对磁盘文件的读写。 ---window 全缓冲大小 4096字节 linux 全缓冲大小 1024字节;
- 行缓冲:当在输入和输出中遇到换行符时,执行真正的IO操作,也就是冲刷缓冲区的数据。比如键盘 输入数据;
- 不带缓冲:也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示 出来。
4、引发缓冲区的刷新
-
遇到换行符\n;
-
缓冲区满(溢出);
-
执行fflush(stdout),手动刷新缓冲区
5、原理实现
说明:
- 录入:输入输出操作的内部采用的缓冲机制,也就是当我们用 scanf() 输入数据时,并不是直接将键盘 录入的数据存储到内存变量中,而是系统会先去输入缓冲区查看是否有符合类型的数据,如果存在将 直接输入缓冲区中的数据到内存变量,此时就不用键盘录入,否则猜需要键盘录入复合类型的数据;
- 输出:相同道理,当我们使用 printf() 输出数据时,也并不是直接将内存变量存储的数据输出到输出设 备,而是先存储到输出缓冲区,当输出缓冲区被充满,或输出缓冲区中出现换行符,或者执行 fflush() ,才会将输出缓冲区的数据输出到标准输出设备。(打印机也是,我们测试用的是控制台显示 终端)
6、预编译
在A函数需要调用B函数时,B函数必须先完成编译或预编译(得到的目标文件后缀为.obj)(预编译命令为#include)
7、printf函数
语法:printf("格式控制",输出列表);
函数原型 int printf(const char * format, ...); 变参 函数
函数作用 将指定格式的数据 输出 到 屏幕终端上(输出设备)
函数参数 format----》指定格式
...---->参数不固定
指定格式---》也就是将数据 以什么样的方式 打印到屏幕上
\n :实现了一个行缓冲;
\0 :相当于空格;
8、字符格式
格式:
%d --> 整型(int)数据,%c --> 字符型(char)数据,%s --> 字符串(字符序列)型数据;
%f --> 单精度浮点型(float)数据(默认输出6位小数),%lf --> 双精度浮点型(double)数据,%e --> 指数型数据(以指数形式输出1个实数,小数点前仅一位非0数字,并输出6位小数);
%hd --> 短整型 short int ;%hhd 字符型的ascii码 char 数据对应的ascii码 的值;
%x --> 十六进制, %#x --> 十六进制 并且 十六进制 的前缀 0x也会打印出来;
#o --> 八进制 ,%#o 八进制 并且 八进制的前缀0打印出来;
%p --> 打印内存的地址
注意:程序开发中最小的就是字符型数据,字符数据只占一个字节,只能存放0~255范围内的整数。
//打印输出整型a,浮点型b(默认输出小数点后6位),双精度浮点型c(指数形式),字符型d printf("%d,%f,%e,%c\n",a,b,c,d);
9、scanf函数
语法:scanf("格式控制",输出列表);
举例:scanf("%d",&a);
练习:
//%3s --> 输出的字符串占3列,因为字符串长为5>3,全部输出; //%7.2s --> 只取字符串前2个字符(向右对齐),左边补空格; //%-5.3s --> 只取字符串前3个字符(向左对齐),右边补空格; //%.4s --> 只取字符串前4个字符; printf("%3s,%7.2s,%-5.3s,%.4s\n","CHINA","CHINA","CHINA","CHINA");
//打印输出整型a,浮点型b(默认输出小数点后6位),双精度浮点型c(指数形式),字符型d,字符串类型e; printf("%d,%f,%lf,%c,%s\n",a,b,c,d,e); printf("请输入:\n"); //从键盘输入整型变量给d1,输入字符类型给c1,输入双精度浮点型给f1; scanf("%d,%c,%lf",&d1,&c1,&f1); //打印输出整型d1,字符型c1,双精度浮点型f1; printf("\n%d,%c,%f\n",d1,c1,f1);
//定义字符型变量a,b,c; char a,b,c; //键盘输入三个连续的字符型变量到地址&a,&b,&c中(程序运行时输入字符的格式需与定义时的格式相符); scanf("%c%c%c",&a,&b,&c); //打印输出三个整型变量a,b,c; printf("\n输出测试字符:%c,%c,%c\n",a,b,c);
//键盘输入一个整型变量和一个长整型变量到地址num和地址lnum; scanf("\n%d,%ld\n",&num,&lnum); //打印输出变量num的八进制整型,十进制整型,十六进制整型和十进制限制5列整型; printf("int-八进制:%o,int-十进制:%d,int-十六进制:%x,int-十进制限制列数:%5d\n",num,num,num,num); //打印输出变量lnum的八进制长整型,十进制长整型,十六进制长整型和十进制限制5列长整型; printf("int-八进制:%lo,int-十进制:%ld,int-十六进制:%lx,int-十进制限制列数:%5ld\n",lnum,lnum,lnum,lnum);
//通过#define预处理命令来定义符号常量PI的值为3.1415926; #define PI 3.1415926; //打印输出浮点型变量s1,s2,s3为总共7位且小数点后2位的格式(右对齐); printf("\ns1=%7.2f\ns2=%7.2f\ns3=%7.2f\n",s1,s2,s3);
10、转型函数
- round(num) --> 四舍五入;
- ceil(num) --> 向上取整;
- floor(num) --> 向下取整。
//如果要在程序中使用数学的计算函数 #include <math.h> //打印输出小数点后两位数字形式的变量3.145,并分别对其进行四舍五入,向上取整以及向下取整的方式; printf("%.2f,%.2f,%.2f\n",round(3.145),ceil(3.145),floor(3.145)); //打印输出以进行四舍五入,向上取整以及向下取整方式的整型变量3.145; printf("%d,%d,%d\n",(int)round(3.145),(int)ceil(3.145),(int)floor(3.145));
九、顺序结构
程序中所有语句都是按自上而下的顺序执行的,不发生跳转。