嵌入式软件工程师&&太极拳
全部博文(548)
分类: LINUX
2011-02-20 20:17:19
重难点:
======
1. 各种隐式类型转换(赋值表达式,运算表达式,三目运算表达式);
2. signed int, signed char在内存中的存放方式;
float, double, long double在内存中的存放方式。
3. 函数和变量的作用域(static, extern, const, volatile, auto, register)
程序的三种基本结构:
1. 顺序结构;
2. 选择结构;
3. 循环结构。
第3章 数据类型、运算符和表达式
C语言的数据类型
===============
C语言的数据类型:
. 基本数据类型:
. int
. char
signed char
unsigned char
. float
. float
. double
. long double
.enum
. 构造数据类型:
. 数组
. struct
. union
. 指针类型
. 空类型
修饰符:short,long,usigned/signed
默认不加signed/unsigned修饰符,表示是signed类型
整形的类型(6种):
[signed] int
unsigned int
[signed] short [int]
unsigned short [int]
[signed] long [int]
usigned long [int]
C语言没有规定int,short,long型所占内存字节数,只规定:short <= int, int <= long。
一般以一个机器字(word)存放int。
变量名:实际上对应一个内存地址。
C语言规定:
标识符只能有字母、数字和下划线3种字符组成,且第一个字符必须为字母或下划线。
注意:编译系统将大写字母和小写字母认为是两个不同的字符。
ANSI C标准没有规定标识符的长度(字符个数),但各个C编译系统都有自己的规定。
在C语言中,要求对所用到的变量作强制定义,也就是"先定义,后使用"。
每个变量被指定为一个确定的类型。在编译时就能为其分配相应的存储单元。
整数变量和常量
==============
在C语言中,整形常量有3种表示形式:
1. 十进制
2. 八进制
以0开头的数。如:0123,即(123)8
3. 十六进制
以0x开头的数。如:0x3c
整数在内存中是以complement(补码)表示的。
正整数:补码和源码相同。
负整数:将该数的绝对值的二进制形式,按位取反再加1。
1000 0001(-127)
1000 0000(-128)
1111 1111(-1)
一个整形常量后面加u或U,表示unsigned int型。
如: 12345u,在内存中,最高位不是符号位。
-12345u,先将-12345转换为补码53191,再按无符号数存储。
一个整形常量后面加l或L,表示unsigned long型。
浮点数
======
浮点数常量
. 有2种表示方法:
1. 十进制小数形式。
如: 0.123, 0.0
2. 指数形式。
如: 123e3或123E3。
注意: 字母e/E之前必须有数字,且e后面的指数必须是整数。
如: e3,123e2.3都是不合法的。
. 注意: C语言编译器默认将浮点型常量作为double双精度。
可以将后缀指定类型。如: 123.4f, 123.4l
. 注意: 一个浮点型常量可以赋给一个float型, double型或long double型变量,
根据变量的类型截取实型常量中相应的有效位数字。
浮点数变量:
1. 浮点型数据是按照指数形式存储的。
C语言标准中没有规定指数位,小数位必须占多少字节,由编译器确定。
gcc中float为:1位符号位,8位指数位(指数需+127),23位小数位。
double为:1位符号位,13为指数位(指数需+4095),50位小数位。
2. 浮点型变量的分类:
float(单精度)
double(双精度)
long double(长双精度)
字符型数据
==========
转义字符及其作用:
字符形式 含义 ASCII代码
\n 换行,将当前位置移到下一行开头 10
\t 水平制表(调到下一个Tab位置,tab为8位) 9
\b 退格,将当前位置移到前一列 8
\r 回车,将当前位置移到本行开头 13
\f 换页,将当前位置移到下页开头 12
\\ 代表一个反斜杠字符"\" 92
\' 代表一个单引号(撇号)字符 39
\" 代表一个双引号字符 34
\ddd 1到3位八进制数所代表的字符
\xhh 1到2位十六进制数所代表的字符
字符变量:
C语言规定: char型占用内存一个字节空间。
C语言允许char型数据和整数直接进行算术运算。
注意: char型数据只占用一个字节,只能存放0~255范围内的整数。
字符串常量:
C语言规定: 在每一个字符串常量的结尾加一个"字符串结束标志"。
C语言以'\0'作为字符串结束标志。
变量赋初值
==========
C语言允许在定义变量的同时使变量初始化。
如: int a = 3;
float f = 3.56;
也可以使定义的变量的一部分赋初值。
如: int a, b, c = 5;
如果对几个变量赋同一个初值,应写成:
int a = 3, b = 3, c = 3;
不能写成:
int a = b = c = 3;
注意:
函数内,定义变量的同时初始化,不是在编译阶段完成的,而是在程序运行时执行本函数时赋初值的。
静态存储变量(static)和外部变量的初始化是在编译阶段完成的。
函数内, int a = 3;
相当于: int a;
a = 3;
各类数值型数据间的混合运算
=========================
整型(int, short, long, char)和浮点型(float, double, long double)可以混合运算。
算术运算符中数据类型的隐式转换规则:
1. char型, short型必定先转换为int型。
float型必定先转换为double型(即使是两个float型运算,也要转换)。
2. 其余类型依据运算符的最高数据类型来转换。
转换的等级为(从高到低):
double
long
unsigned
int
赋值运算符中数据类型的隐式转换规则:
不同类型的整型数据间的赋值归根到底就是一条:
按存储单元中的存储形式直接传输(少字节有符号类型赋给多字节类型时,注意符号扩展)。
1. 将浮点数数据(包括float,double)赋给整型变量时,舍弃浮点数的小数部分。
2. 将整型数据赋给float,double变量时,数值不变,但以浮点数形式存储到变量中。
3. 将一个double型数据赋给float变量时,截取其前面的有效数字,存放到float变量的存储单元中。
注意:可能产生溢出问题。
4. 字符型数据赋给整型变量时,将字符数据放到整型变量存储单元的低8位,如是有符号字符,还会发生符号扩展。
将有符号的char型赋给有符号或无符号的int型时,都会发生符号扩展。使内存中的内容保持不变。
如: char ch = -1;
unsigned int a = ch;
signed int b = ch;
上述变量a,b在内存中都是: 0xffffffff;
5. 将一个int, short, long型数据赋给一个char型变量时,只将其低8位原封不动地送到char型变量。
6. 将带符号的short型赋给int型时,要进行符号扩展。即:如为负数,int型的高16位都补1,如为正数,高16位补0。
7. 将unsigned类型数据赋给一个占字节数相同的非unsigned型整型变量,将unsigned型原样送到非unsigned型变量中。
注意:可能出现数据错误的问题。
8. 将signed类型赋给长度相同的unsigned类型变量时,也是原样赋值(连原有的符号位也作为数值一起传送)。
三目运算符的隐式转换规则:
条件表达式的值的类型为表达式2和表达式3中较高的类型。表达式1 ? 表达式2 : 表达式3;
如: x > y ? 1 : 1.5; 若x > y为真,则整个条件表达式的值是1.0,而不是1;
C语言运算符简介
===============
C语言把除了控制语句和输入输出以外的几乎所有的基本操作都作为运算符处理。
1. 算术运算符 + - * / %(求余,注意两侧均为整型数据)
2. 关系运算符 > < == != >= <=
3. 逻辑运算符 ! && ||
4. 位运算符 << >> ~ ^ & |
5. 赋值运算符 = 及其扩展赋值运算符
6. 条件运算符(三目运算符) ?:
7. 逗号运算符(顺序求值运算符) ,
8. 指针运算符 * &
9. 求字节数运算符 sizeof
10. 强制类型转换运算符 ()
11. 分量运算符 . ->
12. 下标运算符 []
13. 其他 函数调用运算符()
14. 复合赋值运算符(10个) += -= *= /= %= <<= >>= &= |= ^=
除法运算符/:
两个整数相除的结果为整数。
如果除数或被除数中有一个负值,则舍入的方向是不固定的。多数编译器是"向零取整"。
如果参加+,-,*,/运算的两个数中有一个数为实数,则结果为double型。
C语言规定了运算符的优先级和结合性。
使用强制类型转换时,原来变量的类型不会改变。只是得到一个所需类型的中间变量。
自增、自减运算符:
1. ++i, i++的区别
++i为: 先i = i + 1, 再使用i的值
i++为: 先使用i的值, 再执行i = i + 1
2. 自增和自减运算符只能用于变量。不能用于常量或表达式。
如: (-a)++是错误的。
3. 自增和自减的结合性为: 自右至左。
关于表达式使用中的问题说明:
1. ANSI C并没有具体规定表达式中的子表达式的求值顺序,允许各编译系统自己安排。
如: (a++) + (a++) + (a++);
可能的结果为: 3 + 4 + 5, a = 6, 或3 + 3 + 3, a = 6;
2. C语言中有的运算符为一个字符,有的运算符由两个字符组成,在表达式中如何组合呢?
C编译系统在处理时,尽可能多地(自左而右)将若干个字符组成一个运算符。
在处理标识符,关键字时也按同一原则。
如: i+++j; 解释为: (i++) + j; 而不是i + (++j);
3. 在调用函数时,实参数的求值顺序,C标准并没有统一规定。
如: printf("%d, %d\n", i, i++);
----多数系统对函数参数的求值顺序为自右到左。但是也有的编译器可能自左向右。
在赋值表达式中:
表达式(a + b)和常变量都不能作为左值,变量才能作为左值。
右值如果是表达式,此表达式也可以是赋值表达式。
注意赋值表达式和赋值语句的联系和区别:
赋值表达式还可以出现在输出语句,循环语句中;
赋值表达式的最后加一个分号就成为一个语句。
在if的条件中,可以包含赋值表达式,但是不能包含赋值语句。
顺序求值运算符和逗号表达式:
. 一般形式:
表达式1,表达式2,...,表达式n
逗号表达式的值为表达式n的值。
. 优先级和结合方向:
逗号运算符优先级最低,结合方向为自左到右。
. 注意:并不是任何地方出现的逗号都是作为逗号运算符。
如: printf("%d, %d, %d\n", a, b, c); --作为函数中参数间的分隔符。
. 许多情况下,使用逗号表达式的目的只是想分别得到各个表达式的值,而并非一定要得到整个逗号表达式的值,
逗号表达式最常用于for循环语句中
第4章 最简单的C程序设计--顺序程序设计
C语句概述
=========
程序包括:数据描述(由声明部分来实现)和数据操作(由语句来实现)。
数据描述包括定义数据结构和在需要时对数据赋予初值。
数据操作的任务:对已提供的数据进行加工。
C语句分为5类:
1. 控制语句(9种):
if()...else... /*条件语句*/
for()... /*循环语句*/
while()... /*循环语句*/
do...while() /*循环语句*/
continue /*结束本次循环语句*/
break /*中止执行switch或循环语句*/
switch /*多分支选择语句*/
goto /*转向语句*/
return /*从函数返回语句*/
2. 函数调用语句。
3. 表达式语句。
4. 空语句。
;
5. 复合语句:
用大括号{}把一些语句括起来就构成了复合语句。
赋值语句
========
作为赋值表达式,可以包括在其他表达式中。
格式输入和输出
==============
int putchar(int c);
返回值为:返回写入的unsigned char的int类型或EOF
int getchar(void);
返回值为:unsigned char的int类型或EOF
int printf(const char *format, ...);
返回值为:正常返回打印的字符数量,不包含'\0'。发生错误,返回负值。
int scanf(const char *format, ...);
返回值为:正常返回输入的数据个数。发生错误,返回EOF。
printf格式字符:
----------------------------------
格式字符 说明
d, i 以带符号的十进制形式输出整数(正数不输出符号)
o 以八进制无符号形式输出整数(不输出前导符0)
x, X 以十六进制无符号形式输出整数(不输出前导符0x),x输出a~f,X输出A~F
u 以无符号十进制形式输出整数
c 以字符形式输出,只输出一个字符
s 输出字符串
f 以小数形式输出单、双精度数,隐含输出6位小数
e, E 以指数形式输出实数,用e时指数以"e"表示(如1.2e+02),用E时指数以"E"表示(如1.2E+02)
g, G 选用%f或%e格式中输出宽度较短的一种格式,不输出无意义的0.用G时,若以指数形式输出,则指数以大写表示
---------------------------------
printf的附加格式说明字符
---------------------------------
字符 说明
l 用于长整型整数,可加在格式符d,o,x,u前面
m(一个正整数) 数据最小宽度(如: %m.ns, %m.nf, %m.ne)
n(一个正整数) 对实数,表示输出n位小数;对字符串,表示截取的字符个数
# 选择某些代码的另一种转换形式。%#o(添加0),%#x(添加0x),%#e(确保小数点),%#E,%#f,%#g(缀尾0不去除)
0 空格用0填充,如有负号或d,i,u,o,x中出现精度字段,就忽略0。
+ 如果为正数,加+号,如果为负数加-号
---------------------------------
scanf格式字符
---------------------------------
格式字符 说明
d, i 用来输入有符号的十进制整数
u 用来输入无符号的十进制整数
o 用来输入无符号的八进制整数
x, X 用来输入无符号的十六进制整数(大小写作用相同)
c 用来输入单个字符
s 用来输入字符串,将字符串送到一个字符数组中,在输入时以非空白字符开始,以第一个空白字符结束。字符
串以串结束标志'\0'作为其最后一个字符
f 用来输入实数,可以用小数形式或指数形式输入
e, E, g, G 与f作用相同,e与f、g可以相互替换(大小写作用相同)
---------------------------------
scanf附加格式说明字符
---------------------------------
字符 说明
l 用于输入长整型数据(%ld, %lo, %lx, %lu)及double型数据(%lf或%le)
h 用于输入短整型数据(可用%hd, %ho, %hx)
域宽 指定输入数据所占宽度(列数),域宽应为正整数
* 表示本输入项在读入后不赋给相应的变量
---------------------------------
scanf的注意事项:
1. 输入数据不能规定精度。如: scanf("%7.2f", &a); --是非法的,存储的结果也是错误的
2. 如果在"格式控制"字符串中除了格式说明以外还有其他字符,则在输入数据时在对应位置应输入与这些字符相同的字符
3. 用"%c"格式输入字符时,空格字符和"转义字符"都作为有效字符输入。
4. 在输入数据时,遇到以下情况时认为数据结束:
1) 遇空格,或按"enter"或"tab"键;
2) 按指定的宽度结束,如: "%3d",只取3列;
3) 遇非法输入;
第5章 选择结构程序设计
关系运算符和关系表达式
=====================
优先级:
1. 算术运算符 > 关系运算符 > 赋值运算符
2. 关系运算符(<, >, <=, >=) > 关系运算符(==, !=)
关系表达式的值是一个逻辑值:
1 -- 表示真
0 -- 表示假
逻辑运算符和逻辑表达式
======================
C语言编译系统
1. 在表示逻辑运算结果时,以数值1代表"真",以数值0代表"假";
2. 但在判断一个量是否为"真"时,以0代表"假",以非0代表"真"。
优先级:
!(非) > 算术运算符 > 关系运算符 > &&(与) > ||(或) > 赋值运算符。
[注意]:
在逻辑表达式求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执
行该运算符。
如: (m = a > b) && (n = c > d);
当a = 1, b = 2, c = 3, d = 4, m和n原值为1时, m会等于0, 所以后面的(n = c > d)没有执行,n仍为1,不是0。
if语句
======
if语句的3中基本形式:
1. if(x > y)
printf("%d\n", x);
2. if(x > y)
printf("%d\n", x);
else
printf("%d\n", y);
3. if(number > 500)
cost = 0.15;
else if(number > 300)
cost = 0.10;
else if(number > 100)
cost = 0.075;
else
cost = 0;
[注意]: else总是和它上面最近的未配对的if配对。
条件运算符(三目运算符)
======================
表达式1 ? 表达式2 : 表达式3;
条件运算符执行顺序:
1. 先就求表达式1;
2. 如为非0(真),则求解表达式2,此时表达式2的值就是整个条件表达式的值;
3. 如表达式1的值为0(假),则求解表达式3,表达式3的值就是整个条件表达式的值。
表达式2和表达式3不仅可以是数值表达式,还可以是赋值表达式或函数表达式。
如:
a > b ? (a = 100) : (b = 100);
a > b ? printf("%d", a) : printf("%d", b);
switch语句
==========
switch语句的一般形式:
switch(表达式)
{
case 常量表达式1:
语句1
case 常量表达式2:
语句2
.
.
.
case 常量表达式n:
语句n
default:
语句n+1
}
[注意]:
1. 执行完一个case后面的语句后,流程控制转移到下一个case继续执行(如果不希望执行下一个case,务必要加break);
"case 常量表达式"只是起语句标号作用,并不是在该处进行条件判断。
2. 各个case和default的出现次序不影响执行结果(可以先出现default, 再出现case);
3. 多个case可以共用一组执行语句。
如: case 'A':
case 'B':
case 'C':
printf(">60\n");
break;
第6章 循环控制
四种循环
========
label:
语句
goto label;
while(表达式)
{
语句
}
do{
语句
}while(表达式);
for(循环变量赋初值;循环条件;循环变量增量)
{
语句
}
四种循环的区别
==============
1. 在while循环和do...while()循环中,只在while后面的括号内指定循环条件,因此为了使循环正常结束,应在循环体中包含使
循环趋于结束的语句(如: i++)
2. 凡是用while循环能完成的,用for循环都能实现。
3. 用while和do...while()循环,循环变量初始化的操作应在while和do...while()语句之前完成。而for可以在表达式1中实现
4. while循环、do...while()和for循环,可以用break,continue来控制循环,而goto不能用break,continue控制;
for语句的执行过程
=================
for(表达式1; 表达式2; 表达式3) {语句;}
1. 先求解表达式1;
2. 求解表达式2,若其值真(值为非0),则执行for语句中指定的内嵌语句,然后执行下面第3步。若为假(值为0),结束循环,转到
第5步;
3. 求解表达式3;
4. 转回上面第2步继续执行;
5. 循环结束,执行for语句下面的一个语句。