C语言笔记1--类型、运算符与表达式
总论:
变量和常量是程序处理的两种基本的数据对象。声明语句说明变量的名字和类型,也可以指定变量的初值。运算符指定将要进行的操作。表达式则把变量与常量组合起来生成新的值。对象的类型决定该对象可取值的集合以及可以对该对象执行的操作。
一、变量与常量的名字
1、名字是由字母、下划线和数字组成的序列,其第一个字符必须为字母;下划线“_”被看做是字母,但一般不要以下划线“_”开头。
2、名字区分字母大小写,变量名使用小写字母。符号常量名全部使用大写字母,单词之间用下划线分隔。
经验:选择的变量名要能够尽量从字面上表达变量的用途。 局部变量一般使用较短的变量名(尤其是循环控制变量),外部变量使用较长的名字。
二、数据类型
C语言提供了下面4种基本数据类型:
char //字符型,占用一个字节 int //整型,通常反映了所用机器中整数的自然长度 float //单精度浮点型 double //双精度浮点型
数据类型限定符:
1、short 和 long 两个限定符用于限定整型;关键字 int 可以省略,通常也习惯于这么做。
short sh; // short int sh; long counts; // long int counts;
2、类型限定符 signed 与 unsigned 只能用于限定 char 类型和任何整型。
3、long 限定符可以用于双精度浮点型,long double 类型表示高精度浮点数。
三、常量
1、整型常量
类似于 120 的整数常量属于 int 类型;
long 类型的常量以字母 l 或 L 结尾,如120680L;
无符号的常量以字母 u 或 U 结尾。
2、浮点数常量
浮点数常量中包含一个小数点(如 380.5)或一个指数(3.805e+2),也可以两者都有。没有后缀的浮点数常量为 double 类型。后缀 f 或 F 表示float 类型,而后缀 l 或 L 则表示 long double 类型。
注:整型数除了用十进制表示外,还可以用八进制或十六进制表示,前缀0表示八进制037(如十进制31) ,前缀0x 或 0X表示十六进制 0x1f(如十进制31)。
3、字符常量
一个字符常量是一个整数,书写时将一个字符括在单引号中(如‘0’)。字符在机器字符集中的数值就是字符常量值,如‘0’在机器字符集中的数值是48,它与数字0没关系; 再如‘A‘在机器字符集中的数值是65。
注:字符常量一般用来与其他字符进行比较,但也可以像其他整数一样参与数值运算。字符常量‘\0’表示值为0的字符,也就是空字符(null)。我们通常用‘\0’的形式来代替0,以强调某些表达式的字符属性,但其数字值为0。
4、字符串常量
字符串常量也叫字符串字面值,是用双引号括起来的 0 个或多个字符组成的字符序列。
字符串常量就是字符数组,字符串的内部表示使用一个空字符‘\0’作为字符串的结尾。因此,存储字符串的物理存储单元数比括在双引号中的字符数多一个。
注:C语言对字符串长度没有限制,程序扫描到‘\0’结束符表示字符串完。字符串常量存储静态存储区。
标准库函数strlen(char *str)返回字符串 str 的长度( 即空值结束符之前字符数目)。
下面设计strlen函数的一个版本:
int strlen(const char s[]) { int i = 0; while (s[i] != '\0') { ++i; } return i; }
5、枚举常量
枚举是一个常量整型值的列表。
// 预留业务类型 enum RTBPUB_RESVYPE { RESVYPE_IB = 0, //综合帐务 RESVYPE_OCE = 1, //在线计费 RESVYPE_HB = 2, //离线计费 RESVYPE_OCECHARGE = 5 //在线计费充值 };
(1) 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号“ ,”隔开。
(2) RTBPUB_RESVYPE是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
(3) 如果不给枚举赋值,那么第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。
(4) 可以设定枚举成员的值,从而自定义某个范围内的整数。
(5) 枚举型是预处理指令#define的替代。
6、常量表达式
常量表达式是仅仅只包含常量的表达式,这种表达式在编译时求值,而不是在运行时求值。
#define MAXLINE 1000 char g_szline[MAXLINE + 1];
四、声明
变量都必须先声明后使用,一个声明指定一种变量类型。可以在声明同时对变量进行初始化,在声明中,如果变量名的后面紧跟一个等号以及一个表达式,该表达式就充当对变量进行初始化的初始化表达式。
int i = 0; int ilen = MAX + 100;
注:声明语句说明变量的名字和类型,也可以指定变量的初值(初始化)。
任何变量的声明都可以使用 const 限定符限定,该限定符指定变量的值不能被修改;对数组而言,const 限定符指定数组所有元素值都不能被修改。
const int PI = 3.14; const char msg[] = "00000"; int strlen ( const char s[]);
五、算术运算符
二元算术运算符包括:+,-,*,/,%(取模运算符)。
注:整数除法会截取结果中的小数部分。表达式 x % y 的结果是x除以y的余数,当x能被y整除时,其值为0,取模运算符%不能应用于float和double类型。
六、关系运算符和逻辑运算符
1、关系运算符包括下列几个运算符:
> >= < <=
注:他们具有相同优先级。
有两个等性运算符(特殊关系运算符) == != ,优先级仅次于关系运算符。
注:关系运算符的优先级比算术运算低。
2、逻辑运算包括下面两个运算符:
&& ||
逻辑运算有些特殊的属性,有 && 与 || 连接的表达式按从左到右的顺序进行求值,并且,在知道结果值为真或为假后立即停止计算。
运算符&&的优先级比||的优先级高,但两者都比关系运算符和等性运算符的优先级低。
注:根据定义,在关系表达式或逻辑表达式中,如果关系为真,则表达式的结果值的数值为1;如果为假,则结果值的数值为0。逻辑非运算符 ! 的作用是将非0操作数转换为0,将操作数0转换为1。
七、类型转换
当一个运算符的几个操作数类型不同时,就需要通过一些规则把它们转换为某种共同的类型。
一般来说,自动转换是指把“比较窄的”操作数转换为“比较宽的”操作数,并且不丢失信息的转换。
1、由于 char 类型就是较小的整型,因此在算术表达式中可以自由的使用 char 类型的变量,字符型都将被转换为整型。
/* atoi函数:将字符串S转换为相应的整型数*/ int atoi(const char s[]) { int i; int n = 0; for(i=0; s[i]>='0' && s[i]<='9'; i++) { n = 10 * n + (s[i] - '0'); } return n; }
表达式 s[i] - ‘0‘ 能够计算出s[i]中存储的字符所对应的数字值,因为ASCII 码表字符都是相连的。
2、C语言中,很多情况下会进行隐式的算术类型转换。
一般来说,如果二元运算符的两个操作具有不同的类型,那么在进行运算之前先要把“较低”的类型提升为“较高”的类型。
规则:
如果其中一个操作数的类型为long double,则将另一个操作数转换为long double类型。
如果其中一个操作数的类型为double,则将另一个操作数转换为double类型。
如果其中一个操作数的类型为float,则将另一个操作数转换为float类型。
如果其中一个操作数的类型为long,则将另一个操作数转换为long类型。
将char与short类型的操作数转换为int类型。
注:一般来说,数学操作使用双精度double类型的变量。
3、赋值时也要进行类型转换,赋值运算符右边的值需要转换为左边变量的类型,左边变量的类型即赋值表达结果的类型。
4、任何表达式中都可以使用一个称为强制类型转换的一元运算符强制进行显式类型转换。
(类型名)表达式;
八、自增与自减运算符
C语言提供了两个用于变量递增与递减的特殊运算符,自增运算符++使其操作数递增1;
自减运算符--其操作数递减1。
++与--这两个运算符特殊的地方主要表现在:它们既可以用作前缀运算符(用在变量前面,如++n),也可以用作后缀运算符(用在变量后面,如n++),在这两种情况下,其效果都是将变量n的值加1。但是,它们之间有一点不同,表达式++n现将n的值递增1,然后再使用变量n的值,而表达式n++则是先使用变量n的值,然后再将n的值递增1。
/* strcat函数:将字符串拼接*/ void strcat(char s[], char t[]) { int i = 0; int j = 0; while(s[i] != '\0') { i++; } while((s[i++] = t[j++]) != '\0') /*拷贝*/ { ; } }
注:自增与自减运算符只能作用于变量。
九、按位运算符
C语言提供了6个位操作运算符,这些运算符只能作用于整型操作数,即只能作用于带符号或无符号的char、short、int、long。
& 按位与(AND)
| 按位或(OR)
^ 按位异或(XOR)
<< 左移
>> 右移
~ 按位求反(一元运算符)
1、按位与运算符&经常用于屏蔽某些二进制位。
2、按位或运算符|经常用于将某些二进制位置为1。
3、按位异或运算符^当两个操作数的对应位不同时将该位设置为1,否则,将该位设置为0。
4、位移运算符<<与>>分别用于将运算的左操作数左移与右移,移动的位数则由右操作数指定(右操作数的值必须是非负值)。
5、一元运算符~用于求整数的二进制反码,即分别将操作数各二进制位上的1变为0,0变为1。
十、赋值运算符与表达式
在赋值表达式中,如果表达式左边的变量 重复出现在表达式的右边。
如:
i = i + 2;
则可以缩写成:
i += 2;
+=称为赋值运算符。
大多数二元运算符(即有左右两个操作数的运算符,比如+)都有一个相应的赋值运算op=,其中,op可以是下面这些运算符之一:
+ - * / % << >> & ^ |
注:在所有的这类表达式中,赋值表达式的类型是它的左操作数的类型,其值是赋值操作完成后的值。
十一、条件表达式
条件表达式(使用三元运算符“? : ”) expr1 ? expr2 : expr3 ; 在表达式中,首先计算 expr1,如果其值不等于0(为真),则计算expr2 的值,并以该值作为条件表达式的值,否则计算expr3的值,并以该值作为条件表达式的值。
z = (a > b) ? a : b; /*z = max(a,b)*/
注: expr2 与expr3中只能有一个表达式被计算。