今天闲着无聊把书翻看一遍,收获颇丰。
目录
1、数据类型
基本类型数据长度
强制类型转换
bit强制类型转换
2、变量类型
局部变量
全局变量
变量的存储类别
C语言的数据基本类型分为:字符型、整型、长整型以及浮点型。
- 字符型、整型和长整型只能表示整数
- unsigned型只能表达非负整数
- signed型可以表达负整数
- 浮点型表达小数
字符型 | unsigned char | 0 ~ 255 |
signed char | -128 ~ 127 | |
整型 | unsigned int | 0 ~ 65535 |
signed int | -32768 ~ 32767 | |
长整型 | unsigned long | 0 ~ 4294967295 |
signed long | -2147483648 ~ 2147483647 | |
浮点型 | float | -3.4 × e38 ~ 3.4 × e38 |
double | C51中等于float |
在C语言中,不同的数据类型之间是可以混着运算的。当表达式中的数据类型不一致是,首先转换为同一种类型,然后再进行计算。转换原则是:短字节的数据向长字节数据转换。
如下面代码:
unsigned char a;
unsigned int b;
unsigned long c;
c = a * b;
在运算的过程中,程序会自动全部按照unsigned int 型来计算。
比如 a = 10, b = 200, c 的结果就是2000.
那当a = 100, b = 700,时,c为多少?
所以一定要注意每个变量类型的取值范围,c的数据类型是unsigned int型,取值范围为0 ~ 65535,而70000超出了范围,其结果就会溢出,最终c的结果就是(70000 - 65535) = 4464.
那么,如果想让c正常获得70000这个结果,需要把c定义为unsigned long型变量。
unsigned char a = 100;
unsigned int b = 700;
unsigned long c = 0;
c = a * b;
此时c的结果是多少?
答案是:c = 4464
WHY???
因为C语言在不同类型运算时,数值会转换为同一类型运算,但是每一步运算都会进行识别判断,不会进行一个总的分析判断。
比如这段代码中,a和b相乘时,是按照unsigned int类型运算的,所以运算结果也就是unsigned int类型的4464,只是把最终的unsigned int型4464赋值给了unsigned long型的变量c而已。
为避免这种情况,我们可以采用强制类型转换的方法。
在一个变量的前边加上一个数据类型名,并且使用小括号括起来,就表示把这个变量强制转换为括号里的类型。
比如
c = (unsigned long)a * b;
根据符号运算优先级,首先把a强制转换为unsigned long型变量,然后与b相乘,根据C语言运算规则,b就会自动转换成一个unsigned long型的变量,而后运算完毕的结果也是一个unsigned long型的,最终赋值给c。
不同类型变量之间的相互赋值,短字节类型变量向长字节类型变量赋值时,其值保持不变。如
unsigned char a = 100;
unsigned int b = 700;
b = a;
此时程序的最终结果就是b = 100.
但如果是
unsigned char a = 100;
unsigned int b = 700;
a = b;
那么a的值仅仅是取了b的低8位,首先把700变成一个16位的二进制数据,然后取它的低八位出来,也就是188,所以最终结果就是a = 188。这就是长字节数据类型给短字节数据类型赋值的结果,会从长字节类型变量的低位开始截取正好等于短字节类型长度的位,然后赋值给短字节类型。
但是在51单片机中,有一个例外就是bit类型的强制转换。
bit a = 0;
unsigned char b;
a = (bit)b;
在这里,使用bit作强制类型转换,不是取b的最低位,而是判断b是不是0,如果b是0,那么a的结果就是0;如果b是任意非0的其他值,那么a的结果都是1。
在一个函数内部声明的变量就是局部变量,它只在本函数内有效,在本函数之外是不能使用的。
函数的形参也是局部变量。
在函数外声明的变量就是全局变量。其作用域就是从它开始声明的位置一直到程序结束。
全局变量可以被其作用域内的所有函数使用。
一般来说,一个程序文件内的所有全局变量都在文件的开头部分定义,在所有函数之前。
全局函数优缺点:
由于C语言函数只有一个返回值。但是却经常会希望一个函数可以提供或影响多个结果值,这时就可以利用全局变量来实现。但是考虑到全局变量的此特征,应该限制全局变量的使用,过多使用全局变量也会带来一些问题。
(1)全局变量可以被作用域内所有的函数直接引用,可以增加函数间数据联系的途径,但同时加强了函数模块之间的数据联系,使这些函数的独立性降低。对其中任何一个函数的修改都可能会影响到其他函数的执行结果,函数之间过于紧密的联系不利于程序的维护。
(2) 全局变量的应用会降低函数的通用性。函数在执行的时候过多依赖于全局变量,不利于函数的重复利用。目前编写的程序还都比较简单,就一个c文件,但以后要学到一个程序中有多个.c文件,当一个函数被另外一个.c文件调用的时候,必须将这个全局变量的变量值一起移植 。而全局变量不只被一个函数调用,这样会引起些不可预见的后果。
(3) 过多使用全局变量会降低程序的清晰度,使程序的可读性下降。在各个函数执行的时候都可能改变全局变量值,往往难以清楚地判断出每个时刻各个全局变量的值。
(4)定义全局变量会永久占用单片机的内存单元,而局部变量只有进入定义局部变量的函数时才会占用内存单元,函数退出后会自动释放所占用的内存。所以大量的全局变量会额外增加内存消耗。
综上所述,在编程规范上有一条原则,就是尽量减少全局变量的使用。能用局部变量代替的就不用全局变量。
还有一种特殊情况,大家在看程序的时候请注意,C语言是允许局部变量和全局变量同名的,它们定义后在内存中占有不同的内存单元。如果在同源文件中全局变量和局部变量同名,在局部变量作用域范围内,只有局部变量最有效,全局变量不起作用,也就是说局部变量是具有更高的优先级。但是从编程规范上讲,是要避免全局变量与局部变量重名的,从而避免不必要的误解和误操作。
变量的存储类别分为自动、静态、寄存器和外部四种。
动态变量
函数中的局部变量,如果不加static这个关键字来修饰都属于自动变量也叫作动态存储变量。这种存储类别的变量,在调用该函数的时候系统会给它们分配存储空间,在函数调用结束后会自动释放这些存储空间。动态存储变量的关键字是auto,但是这个关键字一般可以省略,所以平时不用。
静态变量
全局变量都是静态变量。
另外的在定义局部变量时前边加上static这个关键字修饰,这个变量就称为静态局部变量。它的特点就是在整个生存期只赋一次初值,在第一次执行该函数时,它的值就是给定的那个初值,而之后在该函数的所有执行次数中,它的值都是上一次函数执行结束后的值,即它可以保持前一次的执行结果。