运算符(Operator)、表达式(Expression)和语句(Statement)
一、 运算符(Operator)
___常见和有用
1.赋值运算符(Assignment Operator)
符号 = 被称为赋值运算符
目的:把值储存到内存位置上。
2. 加法运算符(Addition Operator) / 减法运算符(Subtraction Operator)
+ 和 - 运算符都被称为二元运算符(binary operator),即这些运算符需要两个运算都西昂才能完成操作。
3. 符号运算符
一元运算符(unary operator),一元运算符只需要一个运算对象。
4. 乘法运算符 (Multiplication Operator) / 除法运算符 (Division Operator)
在C语言中,整数除法结果的小数部分被丢弃,这一过程被称为截断(trunction)。
/* divide.c ---- 演示除法 */
#include <stdio.h>
int main(void)
{
printf("integer division: 5/4 is %d \n", 5 / 4); //截断
printf("integer division: 6 / 3 is %d \n", 6 / 3);
printf("integer division: 7 / 4 is %d \n", 7 / 4); //截断
printf("integer division: 7. / 4. is %1.2f \n", 7. / 4.);
printf("integer division: 7. / 4 is %1.2f \n", 7. / 4);
return 0;
}
integer division: 5/4 is 1
integer division: 6 / 3 is 2
integer division: 7 / 4 is 1
integer division: 7. / 4. is 1.75
integer division: 7. / 4 is 1.75
请按任意键继续. . .
5. sizeof运算符和size_t类型
sizeof运算符以字节为单位返回运算对象的大小。(在C中,1字节定义为char类型占用的空间大小。)运算对象可以是具体的数据对象(如,变量名)或类型。如果运算对象是类型(如,float),则必须用圆括号将其括起来。
sizeof返回size_t类型的值。size_t是一个无符号整数类型,是语言定义的标准类型。
// sizeof.c --- 使用sizeof运算符
// 使用C99新增的%zd转换说明 -- 如果编译器不支持%zd,将其改成%u和%lu
#include <stdio.h>
int main(void)
{
int n = 0;
size_t intsize;
intsize = sizeof(int); // int为整数类型
printf("n = %d, n has %zd bytes; all ints have %zd bytes.\n", n, sizeof n, intsize);
//n = 0, n has 4 bytes; all ints have 4 bytes.
// %zd转换说明用于printf()显示size_t类型的值。如果系统不支持%zd,
// 可以用%u或%lu代替之
return 0;
}
6. 求模运算符(Modulus Operator)
求模运算符给出其左侧整数除以右侧整数的余数(remainder)。
13 % 5 读作“13求模5”,求模结果为3.
注,求模运算只能用于整数,不能用于浮点数。
负数求模?
如果第一个运算对象是负数,那么求模的结果为负数;如果第一个运算对象是正数,那么求模的结果为正数:
11 / 5 得 2, 11 % 5 得 1
11 / -5 得 -2, 11 % -5 得 1
-11 / 5 得 -2, -11 % 5 得 -1
-11 / -5 得 2, -11 % -5 得 -1
7. 递增运算符(Increment Operator) / 递减运算符(Decrement Operator)
++ i ( i ++) 等价于i = i + 1;
-- i ( i -- ) 等价于i = i - 1。
++ i ( -- i )和i ++( i --)的区别在于递增(减)行为发生的时间不同。
再看两者的区别的一个例子:
所以有,如果n++是表达式的一部分,可将其视为“先使用n,再递增”;而++n则表示“先递增n,再使用” 。
8. 运算符优先级和求值顺序
运算符 | 结合律 |
---|---|
() | 从左往右 |
+ - (一元) | 从右往左 |
* / | 从左往右 |
+ - (二元) | 从左往右 |
= | 从右往左 |
优先级同算数运算:乘法和除法的优先级比加法和减法高。
二、表达式和语句
表达式由运算符和运算对象组成(运算符操作的对象)。最简单的表达式是一个单独的运算对象,以此为基础可以建立复杂的表达式。
每个表达式都有一个值,表2为一些表达式及其值。
表达式 | 值 |
-4 + 6 | 2 |
c = 3 + 8 | 11 |
5 > 3 | 1 |
6 + (c = 3 + 8) | 17 |
语句是C语言的基本构建块。一条语句相当于一条完整的计算机指令。在C中,大部分的语句都以分号结尾。
leg = 4
只是一个表达式(它可能是一个较大表达式的一部分),而下面的代码则是一条语句:
leg = 4; //赋值表达式语句
printf("%d\n", leg); // 函数表达式语句
最简单的语句是空语句:
; // 空语句
复合语句(或块)由花括号括起来的一条或多条语句组成:
while ( years < 100 )
{
wisdom = wisdom * 1.05;
printf("%d %d\n", years, wisdom);
years = years + 1;
}
三、类型转化
在语句中和表达式中使用不同类型的变量和常量时,C语言会采用一套规则进行自动转换。
类型转换原则:
1. 当类型转换出现在表达式时,无论是unsigned还是signed的char和short都会被自动转换成int。
2. 涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别。
3. 类型的级别从高到低依次是long double、double、float、unsignedlong long、long long、unsigned long、long、unsigned int、int。例外的情况是,当long和int的大小相同时,unsigned int比long的级别高。之所以short和char类型没有列出,是因为它们已经被升级到int和unsigned int。
4. 在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类型。
5. 当作为函数参数传递时,char和short被转换成int,float被转换成double.
// convert.c ---- 自动类型转换
#include <stdio.h>
int main(void)
{
char ch;
int i;
float fl;
fl = i = ch = 'C';
// 字符‘C’被作为1字节的ASCII值储存在ch中。整数变量i接受由'C'转换的整数,即按4字节储存67。
// 最后,f1接受由67转换的浮点数67.00
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);
ch = ch + 1;
i = fl + 2 * ch;
fl = 2.0 * ch + i;
// i的值被转换成浮点数
printf("ch = %c, i = %d, fl = %2.2f\n", ch, i, fl);
// 根据%c转换说明打印时,68被解释成'D'的ASCII码。
ch = 1107;
printf("Now ch = %c\n", ch);
// ch的值超出类型范围,最终ch的值时字符S的ASCII码。(ch的值时1107 % 265)
ch = 80.89;
printf("Now ch = %c \n", ch);
// ch为浮点数,发生截断后,ch的值是字符P的ASCII码。
return 0;
}
其中,
数据对象(data object): 用于储存值的数据存储区域统称为数据对象。
左值(lvalue): 是C语言的术语,用于标识特定数据对象的名称或表达式。
--------对象指的是实际的数据存储,而左值是用于标识或定位存储位置的标签。
副作用(side effect): 副作用是对数据对象或文件的修改。例如,语句:
states = 50; //副作用主要目的是对表达式求值。
它的副作用是将变量的值设置为50。
序列点(sequence point): 是程序执行的点,在该点上,所有副作用都在进行下一步之前发生。在C语言中,语句中的分号标记了一个序列点。
完整表达式(full expression): 指这个表达式不是另外一个更大表达式的子表达式。例如,表达式语句中的表达式和while循环在的作为测试条件的表达式,都是完整表达式。
形式参数(formal argument/parameter): 声明参数就创建了被称为形式参数的变量。
实际参数(actual argument/parameter): 函数调用传递的值为实际参数。