格式(变量类型+变量名称)
变量类型:整数类型(int),浮点数类型(float)
float类型可以存储带小数的数字。
用printf()打印变量,使用%d来处理整数值,使用%f来处理浮点值(%.2f中的.2用于精确控制输出,指出输出的浮点数只显示小数点后面两位)。
如何声明简单变量
1.选择需要的类型。
2.使用有效的字符给变量起一个变量名。
3.按以下格式进行声明:类型说明符 变量名;类型说明符由一个或多个关键字组成。下面是一些示例:
int erest;
unsigned short cash;
4.可以同时声明相同类型的多个变量,用逗号分隔各变量名,如下所示:
char ch, init, ans;
5.在声明的同时还可以初始化变量:
float mass = 6.0E24;
对我们而言,整数和浮点数的区别是它们的书写方式不同;对计算机而言,它们的区别是储存方式不同。
含义:与数学中实数的概念差不多。
在一个值后面加一个小数点,该值就成为一个浮点值。
应用:面向金融和数学的程序。
适用范围:常用于表示非常大或非常小的数。
C语言中的浮点数类型:float、double和long double
优点:能表示包括小数在内更大范围的数。
浮点值的书写形式:类似于科学计数法(用小数乘以10的幂来表示数字)
e后面的数字代表10的指数。
这里关键要理解浮点数和整数的储存方案不同。计算机把浮点数分成小数部分和指数部分来表示,而且分开储存这两部分。因此,虽然7.00和7在数值上相同,但是它们的储存方式不同。在十进制下,可以把7.0写成0.7E1。这里,0.7是小数部分,1是指数部分。图3.3演示了一个储存浮点数的例子。当然,计算机在内部使用二进制和2的幂进行储存,而不是10的幂。第15章将详述相关内容。
C标准规定,float类型必须至少能表示6位有效数字,且取值范围至少是10-37~10+37。前一项规定指float类型必须至少精确表示小数点后的6位有效数字,如33.333333。后一项规定用于方便地表示诸如太阳质量(2.0e30千克)、一个质子的电荷量(1.6e-19库仑)或国家债务之类的数字。通常,系统储存一个浮点数要占用32位。其中8位用于表示指数的值和符号,剩下24位用于表示非指数部分(也叫作尾数或有效数)及其符号。
C语言提供的另一种浮点类型是double(意为双精度)。double类型和float类型的最小取值范围相同,但至少必须能表示10位有效数字。一般情况下,double占用64位而不是32位。一些系统将多出的 32 位全部用来表示非指数部分,这不仅增加了有效数字的位数(即提高了精度),而且还减少了舍入误差。另一些系统把其中的一些位分配给指数部分,以容纳更大的指数,从而增加了可表示数的范围。无论哪种方法,double类型的值至少有13位有效数字,超过了标准的最低位数规定。
C语言的第3种浮点类型是long double,以满足比double类型更高的精度要求。不过,C只保证long double类型至少与double类型的精度相同。
浮点型变量的声明和初始化方式与整型变量相同。
变量类型+变量名称
在代码中,可以用多种形式书写浮点型常量
基本形式:有符号的数字(包括小数点),后面紧跟e或E,最后是一个有符号数表示10的指数。
-1.56E+12 2.87e-3
PS:正号可以省略。
可以没有小数点(2E5)或指数部分(19.28),但是不能同时省略二者。
可以省略小数部分(3.E16)或整数部分(.45E-6),但是不能同时省略二者。
不要在浮点型常量中间加空格。
默认情况下,编译器假定浮点型常量是double类型的精度。
使用双精度进行乘法运算,然后将乘积截断成float类型的宽度。这样做虽然计算精度更高,但是会减慢程序的运行速度。
在浮点数后面加上f或F后缀可覆盖默认设置,编译器会将浮点型常量看作float类型,如2.3f和9.11E9F。使用l或L后缀使得数字成为long double类型,如54.3l和4.32L。注意,建议使用L后缀,因为字母l和数字1很容易混淆。没有后缀的浮点型常量是double类型。 C99 标准添加了一种新的浮点型常量格式——用十六进制表示浮点型常量,即在十六进制数前加上十六进制前缀(0x或0X),用p和P分别代替e和E,用2的幂代替10的幂(即,p计数法)。如下所示:0xa.1fp10
十六进制a等于十进制10,.1f是1/16加上15/256(十六进制f等于十进制15),p10是210或1024。0xa.1fp10表示的值是(10 + 1/16 +15/256)×1024(即,十进制10364.0)。
printf()函数使用%f转换说明打印十进制记数法的float和double类型浮点数,用%e打印指数记数法的浮点数。如果系统支持十六进制格式的浮点数,可用a和A分别代替e和E。打印long double类型要使用%Lf、%Le或%La转换说明。
上溢:计算导致数字过大,超过当前类型能表达的范围时发生,在这种情况下会给toobig赋一个表示无穷大的特定值,而且printf()显示该值为int或infinity。
下溢:在计算过程中损失了原末尾有效位上的数字。C语言把损失了类型全精度的浮点值称为低于正常的浮点值。
原因:计算机缺少足够的小数位来完成正确的运算
现在,我们着重讲解这两种类型的实际区别。
1.整数没有小数部分,浮点数有小数部分。
2.浮点数可以表示的范围比整数大。参见本章末的表3.3。
3.对于一些算术运算(如,两个很大的数相减),浮点数损失的精度更多。
4.因为在任何区间内(如,1.0 到 2.0 之间)都存在无穷多个实数,所以计算机的浮点数不能表示区间内所有的值。浮点数通常只是实际值的近似值。例如,7.0可能被储存为浮点值6.99999。稍后会讨论更多精度方面的内容。
5.过去,浮点运算比整数运算慢。不过,现在许多CPU都包含浮点处理器,缩小了速度上的差距。
作用:用于读取键盘的输入
变量:在程序运行期间可能会改变或者被赋值的数据。
常量:在程序使用之前已经预先设定好了的数据,在整个程序的运行过程中没有变化。
字面量:用于表达源代码中一个固定值的表示法。
字面量几乎与常量没有区别,用良好的定义规范来命名常量可以起到替代字面量的作用。
为什么使用常量比使用字面量的程序的设计风格更好?
1.便于更改,下次你需要修改这个值的时候,只要在常量定义的地方修改下就可以了,如果是字面量,你需要自己去找,一个个地改。
2.使用常量,你可以给它一个有说明意义的名字,这样后期维护的时候有助于别人和你自己明白代码的意图。
所以,一般不建议使用字面量,除非数组下标,循环代码的书写等等,即使是PI这种众人皆知的变量,都有常量的定义。总之,你得让代码变得易懂以维护。
在C语言中,用int关键字来表示基本的整数类型。后3个关键字(long、short和unsigned)和C90新增的signed用于提供基本整数类型的变式,例如unsigned short int和long long int。char关键字用于指定字母和其他字符(如,#、$、%和*)。另外,char类型也可以表示较小的整数。float、double和long double表示带小数点的数。_Bool类型表示布尔值(true或false),_complex和_Imaginary分别表示复数和虚数。
通过这些关键字创建的类型,按计算机的储存方式可分为两大基本类型:整数类型和浮点数类型。
位、字节和字是描述计算机数据单元或存储单元的术语。这里主要指存115储单元。 最小的存储单元是位(bit),可以储存0或1(或者说,位用于设置“开”或“关”)。虽然1位储存的信息有限,但是计算机中位的数量十分庞大。位是计算机内存的基本构建块。
字节(byte)是常用的计算机存储单位。对于几乎所有的机器,1字节均为8位。这是字节的标准定义,至少在衡量存储单位时是这样(但是,C语言对此有不同的定义,请参阅本章3.4.3节)。既然1位可以表示0或1,那么8位字节就有256(2的8次方)种可能的0、1的组合。通过二进制编码(仅用0和1便可表示数字),便可表示0~255的整数或一组字符。【 一个字节存储八位无符号数,这个八位是指的二进制的八位,0--255 】
字(word)是设计计算机时给定的自然存储单位。对于8位的微型计算机(如,最初的苹果机), 1个字长只有8位。从那以后,个人计算机字长增至16位、32位,直到目前的64位。计算机的字长越大,其数据转移越快,允许的内存访问也更多。
字长反映了CPU的性能,字长是指同一时间中处理二进制数的位数。字长越大,同一时间处理的位数越多,数据转移越快,允许的内存访问也越多。
含义:在C语言中,整数是没有小数部分的数。
计算机以二进制存储整数。
int类型是有符号整型,即int类型的值必须是整数,可以是正整数、负整数或零。
用32位存储一个int值。系统用一个特殊位的值表示有符号整数的正负号。
int+变量名;
要声明多个变量,可以单独声明每个变量,也可以在int后面列出多个变量名,变量名之间用逗号分隔。
变量如何获得?
1.赋值
2.通过函数(如,scanf”())获得值
3.初始化变量:为变量赋一个初始值。在C语言中,初始化可以直接在声明中完成。只需要在变量名后面加上赋值运算符(=)和待赋给变量的值即可。
C语言中,把不含小数点和指数的数作为整数。
可以使用printf()函数打印int类型的值。第2章中介绍过,%d指明了在一行中打印整数的位置。%d称为转换说明,它指定了printf()应使用什么格式来显示一个值。格式化字符串中的每个%d都与待打印变量列表中相应的int值匹配。这个值可以是int类型的变量、int类型的常量或其他任何值为int类型的表达式。作为程序员,要确保转换说明的数量与待打印值的数量相同,编译器不会捕获这类型的错误。
通常,C语言都假定整型常量是十进制数。然而,许多程序员很喜欢使用八进制和十六进制数。因为8和16都是2的幂,而10却不是。显然,八进制和十六进制记数系统在表达与计算机相关的值时很方便。例如,十进制数65536经常出现在16位机中,用十六进制表示正好是10000。另外,十六进制数的每一位的数恰好由4位二进制数表示。例如,十六进制数3是0011,十六进制数5是0101。因此,十六进制数35的位组合(bit pattern)是00110101,十六进制数53的位组合是01010011。这种对应关系使得十六进制和二进制的转换非常方便。但是,计算机如何知道10000是十进制、十六进制还是二进制?在C语言中,用特定的前缀表示使用哪种进制。0x或0X前缀表示十六进制值,所以十进制数16表示成十六进制是0x10或0X10。与此类似,0前缀表示八进制。例如,十进制数16表示成八进制是020。第15章将更全面地介绍进制相关的内容。
要清楚,使用不同的进制数是为了方便,不会影响数被储存的方式。也就是说,无论把数字写成16、020或0x10,储存该数的方式都相同,因为计算机内部都以二进制进行编码。
在C程序中,既可以使用和显示不同进制的数。不同的进制要使用不同的转换说明。以十进制显示数字,使用%d;以八进制显示数字,使用%o;以十六进制显示数字,使用%x。另外,要显示各进制数的前缀0、0x和0X,必须分别使用%#o、%#x、%#X(在转化说明符间加“#”)。
dec 十进制 octal 八进制 hex 十六进制
C语言提供3个附属关键字修饰基本整数类型:short、long和unsigned。应记住以下几点。
1.short int类型(或者简写为short)占用的存储空间可能比int类型少,常用于较小数值的场合以节省空间。与int类似,short是有符号类型。
2.long int或long占用的存储空间可能比int多,适用于较大数值的场合。与int类似,long是有符号类型。
3.long long int或long long(C99标准加入)占用的储存空间可能比long多,适用于更大数值的场合。该类型至少占64位。与int类似,long long是有符号类型。
4.unsigned int或unsigned只用于非负值的场合。这种类型与有符号类型表示的范围不同。例如,16位unsigned int允许的取值范围是0~65535,而不是-32768~32767。用于表示正负号的位现在用于表示另一个二进制位,所以无符号整型可以表示更大的数。
5.在C90标准中,添加了unsigned long int或unsigned long和unsigned int或unsigned short类型。C99标准又添加了unsigned long long int或unsigned longlong。
6.在任何有符号类型前面添加关键字signed,可强调使用有符号类型的意图。例如,short、short int、signed short、signed short int都表示同一种类型。
整数类型 | |||||
整数类型(简写) | 存储空间 | 适用场合 | 取值范围 | 优点 | 是否有符合类型 |
int | 32位 | 必须是整数,正整数、负整数、零 | ‘-32768——32767 | 有 | |
short int(short) | 比int少 | 较小数值 | ‘-32768——32767 | 节省空间 | 有 |
long int(long) | 比int多 | 较大数值 | ‘-2147483648——2147483647 | 有 | |
long long int(long long) | 比long多、64位 | 更大数值 | ‘9223372036854775808——9223372036854775807 | 有 | |
unsigned int(unsigned) | 16位 | 非负值 | ‘0——65535 | 用于表示正负号的位现在用于表示另一个二进制位 | 无 |
其他整数类型其他整数类型的声明方式与int类型相同,下面列出了一些例子。不是所有的C编译器都能识别最后3条声明,最后一个例子所有的类型是C99标准新增的。
long int estine;
long johns;
short int erns;
short ribs;
unsigned int s_count;
unsigned players;
unsigned long headcount;
unsigned short yesvotes;
long long ago;
为什么说short类型“可能”比int类型占用的空间少,long类型“可能”比int类型占用的空间多?因为C语言只规定了short占用的存储空间不能多于int,long占用的存储空间不能少于int。这样规定是为了适应不同的机器。例如,过去的一台运行Windows 3的机器上,int类型和short类型都占16位,long类型占32位。后来,Windows和苹果系统都使用16位储存short类型,32位储存int类型和long类型(使用32位可以表示的整数数值超过20亿)。现在,计算机普遍使用64位处理器,为了储存64位的整数,才引入了long long类型。
现在,个人计算机上最常见的设置是,long long占64位,long占32位,short占16位,int占16位或32位(依计算机的自然字长而定)。原则上,这4种类型代表4种不同的大小,但是在实际使用中,有些类型之间通常有重叠。
C 标准对基本数据类型只规定了允许的最小大小。对于 16 位机,short和 int 的最小取值范围是[−32767,32767];对于32位机,long的最小取值范围是[−2147483647,2147483647]。对于unsigned short和unsigned int,最小取值范围是[0,65535];对于unsigned long,最小取值范围是[0,4294967295]。long long类型是为了支持64位的需求,最小取值范围是[−9223372036854775807,9223372036854775807];unsigned long long的最小取值范围是[0,18446744073709551615]。如果要开支票,这个数是一千八百亿亿(兆)六千七百四十四万亿零七百三十七亿零九百五十五万一千六百一十五。但是,谁会去数?
int类型那么多,应该如何选择?
首先,考虑unsigned类型。这种类型的数常用于计数,因为计数不用负数。而且,unsigned类型可以表示更大的正数。
如果一个数超出了int类型的取值范围,且在long类型的取值范围内时,使用long类型。然而,对于那些long占用的空间比int大的系统,使用long类型会减慢运算速度。因此,如非必要,请不要使用long类型。另外要注意一点:如果在long类型和int类型占用空间相同的机器上编写代码,当确实需要32位的整数时,应使用long类型而不是int类型,以便把程序移植到16位机后仍然可以正常工作。类似地,如果确实需要64位的整数,应使用long long类型。
如果在int设置为32位的系统中要使用16位的值,应使用short类型以节省存储空间。通常,只有当程序使用相对于系统可用内存较大的整型数组时,才需要重点考虑节省空间的问题。使用short类型的另一个原因是,计算机中某些组件使用的硬件寄存器是16位。
通常,程序代码中使用的数字(如,2345)都被储存为int类型。如果使用1000000这样的大数字,超出了int类型能表示的范围,编译器会将其视为long int类型(假设这种类型可以表示该数字)。如果数字超出long可表示的最大值,编译器则将其视为unsigned long类型。如果还不够大,编译器则将其视为long long或unsigned long long类型(前提是编译器能识别这些类型)。【int--若不够--long int--若不够--unsigned long--若不够--long long/unsigned long long】
八进制和十六进制常量被视为int类型。如果值太大,编译器会尝试使用unsigned int。如果还不够大,编译器会依次使用long、unsigned long、long long和unsigned long long类型。【八进制和十六进制:int(默认)--若不够--long--unsigned long--long long--unsigned long long】
有些情况下,需要编译器以long类型储存一个小数字。例如,编程时要显式使用IBM PC上的内存地址时。另外,一些C标准函数也要求使用long类型的值。要把一个较小的常量作为long类型对待,可以在值的末尾加上l(小写的L)或L后缀。使用L后缀更好,因为l看上去和数字1很像。因此,在int为16位、long为32位的系统中,会把7作为16位储存,把7L作为32位储存。l或L后缀也可用于八进制和十六进制整数,如020L和0x10L。
类似地,在支持long long类型的系统中,也可以使用ll或LL后缀来表示long long类型的值,如3LL。另外,u或U后缀表示unsigned long long,如5ull、10LLU、6LLU或9Ull。
#include
int main(void)
{
int i=2147483647;
unsigned int j=4294967295;
printf("%d %d %d\n", i, i+1, i+2);
printf("%u %u %u\n", j, j+1, j+2);
return 0;
}
运行结果是:
2147483647 -2147483648 -2147483647
4294967295 0 1
可以把无符号整数j看作是汽车的里程表。当达到它能表示的最大值时,会重新从起始点开始。整数 i 也是类似的情况。它们主要的区别是,在超过最大值时,unsigned int 类型的变量 j 从 0开始;而int类型的变量i则从−2147483648开始。注意,当i超出(溢出)其相应类型所能表示的最大值时,系统并未通知用户。因此,在编程时必须自己注意这类问题。溢出行为是未定义的行为,C 标准并未定义有符号类型的溢出规则。以上描述的溢出行为比较有代表性,但是也可能会出现其他情况。
打印unsigned int类型的值,使用%u转换说明;打印long类型的值,使用%ld转换说明。如果系统中int和long的大小相同,使用%d就行。但是,这样的程序被移植到其他系统(int和long类型的大小不同)中会无法正常工作。在x和o前面可以使用l前缀,%lx表示以十六进制格式打印long类型整数,%lo表示以八进制格式打印long类型整数。注意,虽然C允许使用大写或小写的常量后缀,但是在转换说明中只能用小写。
C语言有多种printf()格式。对于short类型,可以使用h前缀。%hd表示以十进制显示short类型的整数,%ho表示以八进制显示short类型的整数。h和l前缀都可以和u一起使用,用于表示无符号类型。例如,%lu表示打印unsigned long类型的值。
提示 匹配printf()说明符的类型
在使用 printf()函数时,切记检查每个待打印值都有对应的转换说明,还要检查转换说明的类型是否与待打印值的类型相匹配。
作用:用于存储字符(如,字母或标点符号)
技术层面:char是整数类型,实际上其存储的是整数而不是字符。计算机使用数字编码来处理字符,即用特定的整数表示特定的字符。
char类型被定义为8位的存储单元。一般而言,C语言会保证char类型足够大,以存储系统(实现C语言的系统)的基本字符集。
标准的ASCII码的范围是0——127,只需7位二进制数即可表示。
C语言把1字节定义为char类型占用的位(bit)数,因此无论是16位还是32位系统,都可以使用char类型。
声明char变量的格式:变量类型+变量名称
1.变量类型+变量名称;
2.变量类型+变量名称,变量名称......;
定义:在C语言中,用单引号括起来的单个字符
char broiled;
broiled='T';/*为其赋值*/
broiled=T;/*此时的T是一个变量*/
broiled="T"/*此时"T"是一个字符串*/
如上所示,如果省略单引号,编译器认为T是一个变量名;如果把T用双引号括起来,编译器则认为"T"是一个字符串。
实际上,字符是以数值形式存储的,所以也可使用数字代码值来赋值:
char grade=65;/*对于ASCII来说,这样做没问题,但是这是一种不好的编程风格*/
char grade='A';/*标准*/
用'A'代替65才是较为妥当的方法,这样在任何系统中都不会出问题。因此,最好使用字符常量,而不是数字代码值。
C语言将字符常量视为int类型而非char类型。
eg:在int为32、char为8位的ASCII系统中,有下面的代码:
char grade='B';
本来'B'对应的数值66储存在32位的存储单元中,现在却可以储存在8位的存储单元中(grade)。利用字符常量的这种特性,可以定义一个字符常量'FATE',即把4个独立的8位ASCII码储存在一个32位存储单元中。如果把这样的字符常量赋给char类型变量grade,只有最后8位有效。因此,grade的值是'E'。
单引号只适用于字符、数字和标点符号。
C语言用三种方法打印ASCII打印不出的字符:
1.使用ASCII码
2.使用一些特殊的符号序列(转义序列)表示一些特殊的字符。把转义序列赋给字符变量时,必须用单引号把转义序列括起来。
打印转义序列
eg:
char ch='\a';
printf("%c",ch);
C标准规定警报字符不得改变活跃位置。标准中的活跃位置(active position)指的是显示设备(屏幕、电传打字机、打印机等)中下一个字符将出现的位置。简而言之,平时常说的屏幕光标位置就是活跃位置。在程序中把警报字符输出在屏幕上的效果是,发出一声蜂鸣,但不会移动屏幕光标。
转义字符\b、\f、\n、\r、\t和\v是常用的输出设备控制字符。了解它们最好的方式是查看它们对活跃位置的影响。换页符(\f)把活跃位置移至下一页的开始处;换行符(\n)把活跃位置移至下一行的开始处;回车符(\r)把活跃位置移动到当前行的开始处;水平制表符(\t)将活跃位置移至下一个水平制表点(通常是第1个、第9个、第17个、第25个等字符位置);垂直制表符(\v)把活跃位置移至下一个垂直制表点。
这些转义序列字符不一定在所有的显示设备上都起作用。例如,换页符和垂直制表符在PC屏幕上会生成奇怪的符号,光标并不会移动。只有将其输出到打印机上时才会产生前面描述的效果。
接下来的3个转义序列(\\、\'、\")用于打印\、'、"字符(由于这些字符135用于定义字符常量,是printf()函数的一部分,若直接使用它们会造成混乱)。如果打印下面一行内容:
Gramps sez, "a \ is a backslash."
应这样编写代码:
printf("Gramps sez, \"a \\ is a backslash.\"\n");
我认为\\,\',\"就是为了区别\n和"".
用八进制ASCII码表示一个字符,可以在编码值前面加一个反斜杠(\)并用单引号括起来。
eg:
beep='\007';
可以省略前面的0,'\07'甚至'\7'都可以。
用十六进制形式表示字符常量,即反斜杠后面跟一个x或X,再加上1~3位十六进制数字。
使用ASCII码时,注意数字和数字字符的区别。
PS:无论是普通字符还是转义序列,只要是双引号括起来的字符集合,就无需用单引号括起来。双引号中的字符集合叫字符串。
如果要在转义序列(假设使用'\f')和ASCII码('\014')之间选择,请选择前者(即'\f')。这样的写法不仅更好记,而且可移植性更高。'\f'在不使用ASCII码的系统中,仍然有效。
如果要使用ASCII码,为何要写成'\032'而不是032?
首先,'\032'能更清晰地表达程序员使用字符编码的意图。其次,类似\032这样的转义序列可以嵌入C的字符串中,如printf("Hello!\007\n");中就嵌入了\007。
printf()函数用%c表明待打印的字符;
用%d表明待打印的变量的值,打印的是一个整数;
%c转换说明告诉printf()打印该整数值对应的字符。
printd()函数中的转换说明决定了数据的显示方式,而不是数据的存储方式。
char 有符号类型:-128~127
无符号类型:0~255
用于表示正负号的位现在用于表示另一个二进制位,所以无符号整型可以表示更大的数。
根据C90标准,C语言允许在关键字char前面使用signed或unsigned。这139样,无论编译器默认char是什么类型,signed char表示有符号类型,而unsigned char表示无符号类型。这在用char类型处理小整数时很有用。如果只用char处理字符,那么char前面无需使用任何修饰符。
作用:用于表示布尔值,即逻辑值true和false
表示方法:值1表示true,值2表示false【在原则上,只占用1位存储空间】
int32_t 表示32位的有符号整数类型
精确宽度整数类型是可选项。
定义:一些类型名保证所表示的类型一定是至少有指定宽度的最小整数类型。
eg:int_least8_t是可容纳8位有符号整数值的类型中宽度最小的类型的一个别名。
如果某系统的最小整数类型是16位,可能不会定义int8_t类型。尽管如此,该系统仍可使用int_least8_t类型,但可能把该类型实现为16位的整数类型。
定义:可使计算达到最快的类型集合。
最大的有符号整数类型:intmax_t(可存储任何有效的有符号整数值)
最大的无符号整数类型:uintmax_t
(这些类型比long long和unsigned long类型更大)
一般而言,虚数类型都是可选项
类型:float_Imaginary、double_Imaginary和long double_Imaginary
类型:float_Complex(包含两个float类型的值,分别表示实部和虚部)、double_Complex和long double_Complex