2.2
可以在一条语句中声明多个同类型的变量
在变量声明语句中对变量进行赋值叫变量的初始化,所有变量都应该初始化
变量可以用来表示一个固定的数字
变量也可以表示一组相关数字(任何时候只使用其中一个数字,每个数字使用完成后就不再使用了)
计算机内存中的每个存储位置有一个编号,不同存储位置的编号不同,只有通过编号才能找到存储位置,这个编号叫地址
计算机可以根据一个变量找到一个地址,根据这个地址才能找到一个存储位置
当不能通过变量找到对应存储位置的时候就需要直接通过地址来找
变量>地址>存储位置
2.3
scanf函数调用语句中必须使用地址表示存储位置,包含stdio.h文件
使用占位符表示存储类型
scanf函数调用语句中不要加\n
双引号中可以加入不是占位符的内容,但用户必须把这些不是占位符的内容在键盘上按顺序输入,否则计算机不能得到正确的数据
可以在一条函数调用语句中获得多个数据(占位符的个数必须和存储位置的个数一致并且类型也必须一致)
scanf(“%*[^\n]”);
scanf(“%*c”);
可以丢掉留在输入缓冲区的数据
字符类型是一种数据类型,char
这个数据类型中一共包括256个不同的数值,其中每个数值可以用来代表一个字符(例如‘a’,‘+’,‘%’,‘5’…)
每个字符有2个身份:字符身份和数字身份
ASCII码表记录所有字符数值两个身份间的对应关系
256个字符被分成2组,每组128个
其中一组的数字身份在所有计算机上都一样,它们的数字身份从0到127
另外一组的数字身份在不同的计算机上可能不同,有可能从-128到-1,也可能是128到255
所有小写英文字符的数值身份是连续排列的,‘a’的最小,‘z’的最大
大写英文字符的数字身份是连续排列的,阿拉伯数字字符的数字身份也是连续排列的
无符号字符类型也是一种数据类型,unsigned char表示
这个数据类型同样包含256个字符数值
这个数据类型规定所有字符数值的数字身份是从0到255
‘\n’ 换行字符
‘\r’ 回车字符(把打印位置调整到行开头)
‘\t’ 制表符(让后面的字符出现在下一段的开头)
‘\’ 表示
‘"’ 表示“
‘’’ 表示‘
当希望在程序中处理文字信息的时候可以考虑采用字符类型
短整数使用short表示,范围从-32768到32767,共65536个
无符号短整数unsigned short表示,范围0到65535,有65536和不同的整数
长整数用long或long int表示
在不同计算机不同,有2的32次方,从-2的31次方到2的31次方
无符号长整数用unsigned long或unsigned long int表示,从0到2的32次方
整数类型用int表示,同long
无符号整数类型用unsigned int表示,同long
整数类型之间的区别主要是所表示的数字范围不同,它们所表示的数字范围是逐渐扩大的
C语言中使用浮点类型表示带小数点的数字
浮点类型分为单精度浮点类型和双精度浮点类型
单精度浮点类型用float表示,双精度浮点类型用double表示
单精度浮点类型能记录的小数点后面位数少,双精度浮点类型记录的小数点后面的数字多
程序中整数后面加上u表示这个整数是无符号整数类型的
程序中带小数点的数字默认的是double类型的,可以在数字后面加f表示他死单精度浮点类型的
数据类型和占位符的对应关系
char %c和%hhd
unsigned char %c和%hhu
%c对应字符身份,%hhd%hhu对应数字身份
short %hd
unsigned short %hu
long %ld
unsigned long %lu
int %d
unsigned int %u
float %f或%g
double %lf或%lg
%f和%lf 会保留小数点后面无效的0,%g和%lg而不会
2.4 csd14030402am
不同类型的数据支持不同的处理方法
不同类型的数据采用同样的方法处理得到的结果可能不同
%nd也可以作为占位符打印整数,其中n 代表一个数字,这种占位符要求打印结果在屏幕上一代占n个位置
%-nd作占位符要求有效数字出现在n 个位置的左边
%0nd作占位符打印时空出来的位置填字符0而不是空格
%n.mf作占位符可以打印浮点数据,整个打印结果一共占n个位置,其中小数点后面的部分占m 个位置
计算机内存由大量的字节构成,任何两个字节都是类似的,任何一个存储位置一定是由多个相邻的字节合并而成的
计算机内存中每个字节有一个独立的地址,这些地址是连续排列的
存储位置的地址是构成他的所有字节中最小的地址
不同整数类型之间的区别主要是由他们所包含的字节的个数不同造成的
sizeof关键字可以用来获得一个数据类型或一个变量所占的字节个数
sizeof可以用来计算一个公式结果的大小
sizeof关键字中对变量内容做的任何修改都不会真正发生
使用一组0和1表示数字的方式叫二进制
计算机内部就采用二进制的方式表示数字
数字的二进制表示方式种每个数位上不是0就是1,所以叫二进制
二进制和十进制只是同样的数字的不同表示方式,任何数字既可以采用二进制方式表示也可以采用十进制方式表示
数字二进制表示方式在中每个数位有一个编号,最右边的编号是0,向左一次递增
二进制表示方式中每个数位的1单独对应一个数字,这个数字的数值是2的位数次方
二进制表示方式中两个相邻的1之间有倍数关系,左边的1是右边1的两倍
二进制到十进制的转换
把二进制表示方式中所有的1对应的数字找出来然后求和就得到整个二进制表示方式所对应的十进制表示方式
0110 1010
26+25+23+21=64+32+8+2=106
十进制转换二进制的方法
1.首先把十进制数字拆成几个二进制整数次方之和,然后把每个拆分结果转换成二进制某个数位上的1,把其他数位补0
77=64+8+4+1=26+23+22+20=0100 1101
2.除以2取余数倒着写
采用上述方法计算得到的二进制表示方式叫原码,计算机内部采用补码方式记录数字,非负数的原码和补码一样
一个字节中可以记录八个二进制数位
八进制和十六进制是二进制的简写方式
把一个二进制表示方式从右到左每三个数位分成一组,每组用一个0到7之间的数字代替得到的结果就是数字的八进制表示方式
在程序中可以直接使用八进制方式表示数字,要求前边加一个0避免和十进制混淆
%o做占位符可以把一个整数的八进制表示形式打印在屏幕上
把二进制表示形式从右到左每四个数位分成一组,每组用一个数字表示得到的结果就是十六进制表示方式(使用a到f代表10到15这六个数字)
在程序中可以直接使用十六进制表示数字,必须在前边加0x作为开头,避免和其他进制混淆
使用%x或%X做占位符可以吧一个整数的十六进制表示形式打印在屏幕上(%x打印的字母都是小写的,%X打印的字母都是大写的)
2.5
二进制加一的规则是把从右到左连续多个1变成0,吧遇到的第一个0变成1
负数二进制表示方式的计算规则
首先把得到相反的非负数的二进制
把上一步结果中的每个数位变成相反数值
把上一步结果加一
以上方法计算得到的二进制表示方式就是负数的二进制补码
每个数据类型中有一个特殊的二进制表示形式(最左边的二进制数位是1,右边的所有位数都是0),这个二进制形式表示这个数据类型中的最小整数
这种办法可以根据任何一个整数二进制计算出相反数的二进制(不论已知的二进制是正还是负)
有符号数据的二进制表示形式中最左边的数位叫做符号位,如果符号位是0表示数字是正的,否则表示负的
无符号数据没有符号位,符号位不等同于正负号
把一个代表整数的数字赋值给一个代表整数类型的变量时,会保持二进制内容不变(十进制结果会改变)
有符号数据左边扩充二进制数位数时每个扩充出来的数位上都填充符号位
2.6
2.6 csd14030403am
加减乘除和取余操作符(+,-,*,/,%)
,也是一个操作符
,操作符可以把两个表达式合并成一个,合并后表达式的计算结果是后一个表达式的结果
,操作符的优先级比赋值操作符低
一条语句中可以多次使用赋值操作符,这时优先计算右边的赋值操作符
布尔值包括真和假两个
计算机内部使用1表示真,0表示假
C语言中可以把任一个整数当布尔值使用,整数0当做布尔值使用是假,其他整数当布尔值使用时是真
逻辑表达式的计算结果只能是布尔值
逻辑表达式需要使用逻辑操作符编写
双目逻辑操作符包括==(相等),!=(不等),>(大于),<(小于),>=(大于等于),<=(小于等于)
!是一个单目逻辑操作符,它可以写在一个布尔值的左边,它可以把原来的布尔值变成相反数
双目逻辑操作符只能用来编写简单的逻辑表达式(只包含一个双目逻辑操作符的逻辑表示式)
多个逻辑表达式可以采用与(&&)和或(||)连接
采用与(&&)连接的多个逻辑表达式只有当所有简单逻辑表达式的结果都是真的时候合并后复杂表达式结果才是真,否则是假
采用或(||)连接的多个逻辑表达式只要有一个简单逻辑表达式的结果是真则合并后的表达式结果就是真,否则是假
与和或这两个逻辑操作符都有短路特性,如果前一个表达式的结果可以决定整个表达式的结果
逻辑操作符的优先级低于算数操作符
位操作符直接操作二进制数位
双目操作符包括按位与(&),按位或(|)和按位异或(^)
双目位操作符先把两个参与计算数字的二进制表示方式写出来,然后把它们对应数位之间进行计算
按位与(&)把对应数位上的数字做与计算
按位与可以把某些二进制数位清0
按位或(|)把对应数位上的数字做或计算
按位或可以把某些二进制数位置1
任何数位和1做按位或计算结果是1,和0做按位或结果不变
按位异或(^)把对应数位上的数字做异或计算
按位异或可以把某些二进制数位上的数字求反
任何数位和1做异或结果变成相反数值,和0做异或结果不变
~是一个单目位操作,它可以对一个数字的每个二进制数位求反
可以对字节中的所有二进制数位向左或向右移动n个位置,为了实现该效果需要使用移位操作符
<<表示向左移位
表示向右移位
他们都是双目操作符,需要左右各有一个数字。左边的数字要进行移位操作,右边的数字表示移动的位数
他们不会改变左边数字的内容
如果在移位过程中没有丢失有效数位,则左移n位相当于乘以2的n次方,右移n位相当于除以2的n 次方
左移是右边的位置上一定补0
无符号类型整数右移时左边的空位置上一定补0,有符号类型整数右移时左边的空位置上一定补符号位
&操作符可以根据一个变量或存储位置获得地址数据
*操作符可以根据一个地址获得对应的存储位置
三目操作符可以根据一个布尔值从两个不同的表达式中选择一个进行计算
三目操作符的使用方法如下
布尔值?表达式1:表达式2
布尔值为真则采用前面的表达式,否则采用后面的表达式
2.7
当一个表达式中多个数据的类型不一致的时候计算机会首先把它们转换过程由计算机自动完成,叫做隐式类型转换
隐式类型转换过程中会把char和short类型数据转换成整数类型
如果既有整数类型数据又有浮点类型数据则会把整数类型转换成浮点类型
如果所有数据的类型不同但所占空间大小一样,则吧整数转换成单精度浮点数,有符号数转换成无符号数
C语言程序中可以随时给任何数据指定类型,因此C语言是弱类型语言
给数据指定类型的做法叫强制类型转换
强制类型转换不受规则约束,有可能出错
在强制类型转换时计算机会生成一个新数据,然后用旧数据对新数据做初始化
强制类型转换不会改变旧数据
流程控制语句可以让程序中的语句不再从上到下顺序执行
分支是一种流程控制语句,他可以从几组语句中挑选出一组执行而忽略其他组
if关键字可以用来编写分支语句
在if语句中为每组语句编写一个逻辑表达式,逻辑表达式结果为真时执行这条语句,否则不执行
如果多个分组在任何时候最多会执行其中一个可以使用else关键字把它们合并
如果合并后的多个分组不可能都不执行则可以把最后一个分组的逻辑表达式省略
switch…case语句也可以用来实现分支,每段都要使用break结束
2.8
循环也是一种流程控制语句,它可以让程序中一段语句反复执行很多遍
for关键字可以用来编写循环语句
如果在整个循环过程中可以找到一组规律变化的数字,这时就可以考虑采用for关键字写循环语句
在编写循环之前要声明一个变量,使用这个变量在整个循环执行过程中代表那组数字,这个变量叫做循环变量
采用如下格式藐视循环变量在整个循环中的变化过程
(1;2;3)
其中123分别代表一条语句
语句1负责吧最开始的数字赋值给循环变量
语句2是一条逻辑表达式,标书循环变量的最后数字间的关系
语句3描述循环变量时如何变化的
最后在小括号前边加for关键字,后边加一对大括号,里面是希望反复执行的语句组
可以认为每当循环变量发生一次变化大括号内部的语句就执行一次
break语句可以随时终止整个循环的执行,这条语句执行后循环中的一切都不再执行(循环变量也不再变化)
continue语句可以直接跳到循环大括号的末尾
这两条语句都只能影响直接包含他们的循环语句
假如有如下的for 语句
for(1;2;3)
{
4
}
它以如下分组方式执行
【1,2】【4,3,2】【4,3,2】。。。。
除了第一组外都一样
正常情况下循环会在两组之间结束
如果某一组中最后编号为2的语句执行结果是真则启动下一组,否则结束循环
只要循环正常结束则编号为2的逻辑表达式计算结果一定是假
如果循环采用break语句结束则编号为2的逻辑表达式计算结果一定是真
用for关键字编写的循环中大括号里面的语句有可能根本不执行
对于复杂的循环问题可以考虑把所有要处理的数字进行分组,为每一组指定一个代表数字,使用一个循环描述所有组代表数字的变化过程,内部使用另一个循环描述组内部的数字变化过程
这种代码结构叫循环嵌套
循环嵌套中内部循环的开始数字合结束数字很可能需要根据外部循环的循环变量计算出来
2.9
for循环的多种写法
如果循环大括号中只有一句语句则可以省略大括号
在小括号使用,操作符
、在小括号中临时定义循环变量(c99规范才支持,这种循环变量才有效)
小括号只保留中间
若大括号中没有语句则可以直接在小括号后加;然后省略大括号
把小括号中间的部分省略不写(死循环)
可使用ctrl+c结束程序
while关键字也可以用来编写循环
只要知道循环什么时候应该结束就可以使用while循环
for和while编写的循环完全可以互相替代
大括号里的语句有可能根本不执行
while关键字也可以用来实现空语句与死循环
while语句中也可以使用break;和continue;语句
do…while语句也可以实现循环,这种玄幻中大括号里面的语句至少会执行一次
do{
//反复执行的语句
}while(布尔值);
这种写法也是按照分组方式执行的,分组结果就相当于把while分组中第一周丢掉
求2个数最大公约数如下
scanf函数调用语句可以当做数字使用,如果是0表示没有读到有效数据
goto语句也是一种流程控制语句
goto语句可以决定下一条语句在哪里(通常不用该语句)
2.10
采用数组可以分配内存中一组连续排列的存储位置并使用它们
这些存储位置有前后顺序(地址晓得在前,地址大的在后)
一个数组只有一个名字
数组中每个位置有一个自己的编号,不同存储位置编号不同,最前边的存储位置编号是0,向后依次递增,这些编号叫下标,下标用来区分不同的存储位置
有效下标范围从0到个数减一,超过范围的下标不可以使用
一个数组中所有存储位置的类型必须一样
数组也必须先声明后使用
下标是处理数组过程中重要的依据,经常需要处理下标然后通过下标再处理数组中的位置
对数组的操作通常使用循环实现,在循环中使用循环变量描述下标的变化过程,在大括号中对循环变量做下标对应的存储位置做处理
数组也需要初始化
初始化数组需要提供多个数据,每个数据用来初始化一个存储位置
所有初始化数据应该写在一对大括号中,不同数字之间使用,分割
前面的数字用来初始化前边的存储位置,后面的数字用来初始化后面的存储位置
若初始数据的个数多于存储位置的个数,则后面多余的数据被丢失
若初始化数据个数少于存储位置个数,则后面的存储位置自动初始化为0
若个数一样则可以省略存储位置的书写
根据数组找到存储位置的方法也要通过地址
数组名称代表数组第一个存储位置的地址
数组名称加下标可以计算出下标对应存储位置的地址
数组名称不代表存储位置,所以不可以被赋值
2.11
对数组名称进行sizeof计算得到整个数组大小
数组声明语句执行后其中存储位置的格式就不可改变了
变长数组中存储位置的个数在编写完程序后是不确定的(但在执行过数组声明语句后必须确定),c99规范才支持变长数组
变长数组不可以初始化
int arr[num]={1,2,3}; //错误,不可以初始化
在编写程序时无法确定数值的数字叫随机数
rand()标准函数可以获得伪随机数,直接把函数调用语句当数字使用就可以获得伪随机数,为了使用这个标准函数需要包含stdlib.h文件
srand标准函数用来设置随机数种子,可以把任何一个整数作为种子使用,需要包含stdlib.h文件
time标准函数可以获得0时区从1970-01-040时0分0秒到现在所经过的时间,为了使用这个函数需要包含time.h文件
srand(time(0));//随机数
任何程序中srand标准函数应该只执行一次
一维数组只有一个下标,二维数组有两个下标,他们是两种使用内存中连续存储位置的方法,二维数组中第一个下标用来表示某个分组,可以把这个下标叫做组下标,范围是从0到组的个数减一
二维数组中第二个下标用来表示分组中某个存储位置
通常采用循环嵌套结构对二维数组中所有存储位置依次进行处理
二维数组可以被当成一个一维数组进行初始化,也可以当做多个数组进行初始化
如果根据初始化数据的儿歌书可以计算出组的个数则可以在声明二维数组的时候省略组的个数
二维数组名称也代表第一个存储位置的地址,但它和一维数组名称的类型不同
在sizeof计算中二维数组名称代表整个二维数组,计算结果是二维数组中所有存储位置的大小
一维数组名称和二维数组名称类型不同,他们可以相互转换
对一维数组名称取地址操作结果的类型就是二维数组名称,但数值没改变
转换后的二维数组中只有一组数据,其中包括原来一维数组中的所有存储位置
二维数组名称加一个下标就可以转换成一个一维数组,这个一维数组就是二维数组中的某一组数据的位置