51单片机轻松入门—基于STC15W4K系列(C语言版) 李友全 编著:http://www.51hei.com/bbs/dpj-37954-1.html
第2章 C语言基础 1 变量的数据类型(bit、char、int、long、float) 2 变量存储空间(code、data 、xdata) 3 变量存储类型(auto、static)
4 变量作用域 5 运算符 6 分支结构 7 循环结构 8 函数 1 变量的数据类型(bit、char、int、long、float) 常用变量定义举例: bit a; // bit位型变量长度是1个位,取值范围是0和1,通常用作程序中的标志位。 unsigned char b; // 正数运算,占用内存1个字节(8位,运算范围:0 ~ 255) unsigned | int c; | // 正数运算,占用内存2个字节(2*8=16位,运算范围:0 ~ 65535 ) | unsigned | long d; | // 正数运算,占用内存4个字节(4*8=32位) | float f; | | // 带小数点的数值运算 |
数据类型 | 符号 | 说明 | 字节数 | 表示形式 | 数值范围 | 位 型 | 无 | | 1/8 | bit、sbit | 0或1 |
字符型 | 有 | | 1 | char | -128 ~ +127 | 无 | | 1 | unsigned char | 0 ~ 255 |
| 整数型 | 有 | 整型 | 2 | int | -32768 ~ +32767 | 长整型 | 4 | long | -2147483648~ +2147483647 |
| 无 | 整型 | 2 | unsigned int | 0 ~ 65535 | 长整型 | 4 | unsigned long | 0 ~ 4294967295 |
|
|
实型 | 有 | 有效值24位 | 4 | float | (±16777215)× 10±127 |
2 变量存储空间(code、data 、xdata) code :变量存放在程序存储器空间,最主要的用途是存放表格数据。 比如:unsigned char code Table[]={0x12,0x23,… ,0x34};P0 = Table[ i ]; data :变量存放在内部RAM ,访问速度快。 xdata :变量存放在外部RAM, 访问速度慢(单片机内部扩展的xdata 速度仍然很 快) 如果定义变量时没有说明存储空间,此时变量存储空间由keil环境确定,单击工具 栏按钮options for target,选择target选项卡,在Memory model后就可以选择变 量默认存储空间。
void fun() { 3 变量存储类型(auto、static)
auto unsigned char x; static unsigned char y=5; //初次运行时进行初始化赋值1次 x++; y++; } auto:只用于函数内部变量定义,单片机在执行这个函数的时为它分配内存地址, 当函数 执行完毕返回后,auto变量就会被销毁,再次进入这个函数时,它的初值是不确定的, auto变量是局部变量,只允许在定义它的函数内使用,由于auto变量在定义它的函数外的 任何地方都是不可见的,所以允许我们在这个函数外的其它地方或者是其它的函数内定义 同名的变量,它们之间不会发生冲突,因为他们都有自己的区域性,由于函数内部变量默 认存储类型就是动态型auto,所以实际代码中一般都省略了这个关键字。 static:在函数内部,static允许一个变量在重新进入这个函数时能够保持原来的值不 变,在函数内部用static定义的变量在函数初次运行时进行初始化赋值1次, 且只操作一 次,以后每次调用函数时不再重新赋初值而只引用上次函数调用结束时的值,在函数内部 使用static定义的变量是局部变量, 只能在定义该变量的函数内使用该变量。 4 变量作用域 如果一个变量在某个文件或函数范围内是有效的,则称该文件或函数为该变量的作用 域,在此作用域内可以使用该变量,所以又称变量在此作用域内“可见”,通常,变量的 作用域都是通过它在程序中的位置隐式说明的。 局部变量 : ① 在一个函数内部定义的变量是局部变量,只能在函数内部使用,在main主函数内部 定义的变量也是局部变量,其它函数也不能使用主函数中的变量。 ② 局部变量在没有赋值以前的值是不确定的,是以前残留在内存里的随机值,所以在定 义局部变量的时候一定要初始化。 ③ 不同函数中可以使用同名变量,它们作用域不同,因此不会发生冲突。 ④局部变量在函数被调用的过程中动态占有存储单元,调用结束立即释放。 全局变量 : ① 在函数外部定义的变量是全局变量,其作用域是变量定义位置开始至整个程序文件结 束,实际中全局变量一般是在程序的开头位置定义。 ② 全局变量在没有赋值以前系统默认为0。 ③局部变量若与全局变量同名,则在局部变量的作用域内,全局变量存在,但不可见, 全局变量的作用被屏蔽。 ④全局变量在程序运行过程中一直占用RAM存储单元。 5 运算符 C语言中的常用运算符可以归纳为下列7大类: 算术运算符 ( +、 -、 *、 /、 %、 ++、 -- ) 关系运算符 ( <, >, <=, >=, ==, != )输入数值,输出0或1 逻辑运算符 ( && 、||、 ! ) 输入数值,输出0或1 位操作运算符( & 、| 、~ 、^ 、<< 、 >> )输入数值,输出数值 赋值运算符 ( = ) 特殊运算符 ( & 、 * ) 分隔符主要包括这几个:[ ] ( ) { } , : ; (1) if (表达式) { 6 分支结构
语句块; } 示例: if (a >=3) { b = 0; } 说明:① 如果表达式的结果为真(0代表“假”,用非0代表“真”),则执行语句块,否则执行if语 句后面的语句(即语句块后面的语句)。 (2) if (表达式) { } else { } 语句块1;
语句块2; 示例: if (a >=3) { b = 0; } else { b = 1000; } switch(变量表达式) { case 常量表达式1: { 语句块1;} break; // 必须使用break跳出当前switch结构。 case 常量表达式2: { 语句块2;} break; // 必须使用break跳出当前switch结构。 case 常量表达式n: { 语句块n;} break; // 特别提示:default前也必须有break。 default: { 语句块n+1;} break; //必须使用break跳出当前switch结构。 } 补充说明: ① “变量表达式”结果必须是字符型、整型或长整型,而不能是浮点型,否则编译错误。 ② “break;”语句可放在{ 语句块X} 外,如上面格式所示,也可放在{ 语句块X}内的最后 一行。 ③ 多个case语句可以共享一组执行语句,例如下面的语句case 1与case 2执行同一个语 句块。 case 1: case 2:{ 语句块;} (1) while (表达式) { 7 循环结构
语句块; } 说明:如果表达式的结果为真(0代表“假”,用非0代表“真”),则执行语句块,否则执 行while语句后面的语句(即语句块后面的语句)。 特殊的: while (1) 构成1个无限循环过程。 (2) do { 很常用
语句块; } while (表达式); // 当表达式的值为真(非0都算作真)时继续执行循环体
(3) for (表达式1;表达式2;表达式3) { 语句块; } for循环的等效结构如下。 for (循环变量初值;循环条件;循环变量增值) { 语句块; } 特殊的:for (;;); // 构成1个无限循环过程 示例1:void print_message() { 8 函 数
print (“How do you do!
” ); } 无参数函数定义格式: 返回值类型 函数名() { 变量声明; 语句块 ; return (变量或表达式); }
可以不用 示例2:int max (int x,int y) { int z ; z = x > y ? x:y; return (z); } 带参数函数定义格式: 返回值类型 函数名(类型 形参1,类型 形参2,…) { 变量声明; 语句块 ; return (变量或表达式); } Ø 有些函数即将执行完毕时会返回一个值,函数定义时的“返回值类型”应该与函数内部 return语句行的变量数据类型相同,也就是说只要按变量类型来定义“返回值类型”就 行了,若函数不需要返回值,“返回值类型”要写作“void”,此时函数内部也不需要 return语句。 Ø return语句功能是立即从所在的函数中退出, 返回到调用它的程序中去,同时还能返回 一个值给调用它的函数,一个函数中可以有多个return 语句(如分支结构),执行到 哪各return 语句则哪个return 语句起作用。 Ø 形式参数是指调用函数时要传入到函数体内参与运算的变量,形式参数必须指定类型, 它可以有任意多个或没有(由于单片机RAM存储空间有限,所以实际上达不到任意多 个),当不需要形式参数时括号内可为空或写入“void”表示,但括号不能少。 调用格式(1)函数名(变量或常数1,变量或常数2,…); 示例:Switch (x,y) ;print_message(); 调用格式(2) V = 函数名(变量或常数1,变量或常数2,…); 示例:z = max (5,9) 说明:当函数有多个参数时各参数要用逗号隔开。 Ø 传值调用方式:主调函数的实参可以是常数、变量、数组元素(比如array[ i ])、结构体 成员变量(比如student.name),传递过去的是常数、变量、数组元素或结构体成员变量 里面的值,不管被调函数里面内容如何,调用结束后主调函数参数都不会发生变化。 Ø 传地址调用方式:当用数组名作为函数实参时,是将数组所在内存单元首地址传递给函 数,而不是将整个数组元素都复制到被调函数中去,被调函数直接操作数组内的元素,所 以被调函数的操作会影响到主调函数的实参,这里是传地址调用。例如: int array[]={10,12,20,18,9,11,}; MaxNum=avrage(array,6); 注意: ① 函数定义行结尾不能有分号,函数调用语句结尾必须有分号。 ② 主调函数的实参与被调函数的形参个数和类型必须一致,否则在传值的过程中发生自动类 型转换可能导致最终结果不正确。 ③ 如果被调函数书写在主调函数之后,则应在文件的开头(即所有函数外的最上端)声明被 调函数,声明方法是将函数定义的一整行复制到文件开头并在行尾添加分号即可。 |