该文章内容整理自《C程序设计(第四版)》、《高质量C编程指南》、以及网上各大博客
数据表示
(1). 常量
- 整型常量:100、123等整数常量
- 实型常量:123.456、3.14等十进制小数形式;12.3e45、-6.7E-89等指数形式(e或E前必须有数字,之后必须为整数)
- 字符常量:‘1’、‘a’、‘A’、’#‘等单个字符;’"’、’\’、’\n’、’\t’等不能显示的转义字符。另外,’\101’表示八进制ASCII码数字101,即65,也即’A’;’\x41’则表示十六进制ASCII码也即’A’。这种方法可以表示ASCII码中的所有字符。另外,ASCII码使用7位二进制表示,使用8位表示时称扩展ASCII码,而Unicode码则是综合不同语言字符的字符集,ASCII码是Unicode码的子集。此外,使用\u或\U开头对字符进行编码能表示比Unicode码更多的字符。此时,\u后面为8个十六进制位,\U后面则为16个十六进制位。而在C++11中还支持UTF-8标准,此时用前缀u8表示
- 字符串常量:“ABC”、“123"等。注意"AB”"CD"与"ABCD"等价,也即在赋值或在printf中输出时将双引号内的字符串常量拆开成多个双引号的字符串常量是可以的
- 符号常量:用#define指定一个符号代表一个常量,在预处理后将符号位置换成常量。如#define PI 3.1415926(注意没有分号)
(2). 变量
变量名实际上是以一个名字代表的存储地址。在对程序编译链接时由编译系统给每个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。变量、函数等对象的声明和定义的区别在于是否分配内存空间
(3). 常变量
即const。如const int a = 3;或int const a = 3;。用于使变量只读,不能修改。另一种用法是用于函数参数,以防函数调用时修改实参。const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数。所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
(4). 标识符
指变量名、符号常量名、函数名、数组名、类型名等有效字符序列。由字母、数字、下划线组成,不能以数字开头。且不能以双下划线和下划线加大写字母开头,这其中有些名字已被保留实现
数据类型
主要分类如下
(1). 整型数据
- 基本整型(int):2或4字节,以补码形式存储
- 短整型(short int):1或2字节,存储方式同int
- 长整型(long int):4字节,存储方式同int
- 双长整型(long long int):8字节,存储方式同int
C标准没有具体规定各种类型所占用的存储单元长度,而是由各编译系统自行决定。C标准只要求long型数据长度不短于int型,short型不长于int型(可用sizeof查看所占字节数)。另外,系统会根据整型常量的大小来按不同的整型数据存储,而在整数末尾加L或l则直接按长整型存储
(2). 字符型数据
字符变量(char):1字节。取值0-127。有些系统需要更多字符时可能会用到扩展的ASCII字符,此时则用到unsigned char,即第一位不固定为0,这表明char是否含符号可以自行设置。另外,char的一个用途是以比short更小的空间存储整数
(3). 浮点型数据
- 单精度浮点型(float):4字节,6位有效数字。浮点数类型最好不要用来作判断等于的条件,此时应使用差的绝对值
- 双精度浮点型(double):8字节,15位有效数字。在进行浮点数算术运算时会自动将float转换成double再计算。并且,系统对单精度和双精度都是按双精度处理,分配8字节,只是存储时按不同的形式存储。所以而对float a = 3.1415926系统会发出警告提醒用户将一个双精度常量转换为float型并因此存在精度损失。此时可以在3.1415926末加上F或f强制转换为float类型则不会出现警告。同时,加L或l则表示为long double型
- 长双精度型(long double):8或16字节,15或19位有效数字
(4). 逻辑型数据
逻辑变量(bool):用0代表false,用非零值代表true。注意不一定用1代表true。用非零值给bool变量赋值时会隐式转换为true,用零值则会隐式转换为false
数据运算
C语言主要包含运算符及其优先级如下
常见的优先级理解错误问题如下
两个实数相除为双精度实数,两个整数相除为整数。对-5/3,有的系统为-1,有的为-2
对算术表达式的计算顺序,不同级运算符按优先级计算,同级运算符按从左到右计算
在不同类型变量之间赋值、对不同类型变量进行混合运算,参数传递给函数时,不同类型按char、short、int、long、long long、float、double,有符号向无符号等原则,转化为更高的同级运算符计算或转换为相应的类型,此时称为隐式转换。隐式转换有可能导致数据精度发生变化。而用括号()进行显式类型转换时有两种表示方法,为(long) a或long (a),此时不会改变变量a,而是创建一个新的指定类型的值
简单来说,优先级有:算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符。逻辑运算符中“逻辑非 !”除外。
短路规则:在整个逻辑表达式中,同级运算符从左到右运算,当前一个子表达式的运算结果能确定整个表达式的值时,剩余的表达式统统免于运算,而以当前这个子表达式的值作为整个表达式的值
对于后自增后自减运算符,当遇到逗号或者分号时就会认为计算单位结束,开始执行运算
关于逗号运算符:a=1,2;表示两个语句a=1和2,因此整个语句执行完后a=1。b=(1,2);先执行语句(1,2),其中先执行1,再执行2,因此最后b=2