C Primer Plus学习笔记- 运算符表达式和语句

Posted Sch01aR#

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C Primer Plus学习笔记- 运算符表达式和语句相关的知识,希望对你有一定的参考价值。

基本运算符

赋值运算符:=

在C语言中,=不是“相等”,而是赋值运算符,把左边的值赋给右边的变量

a = 2018;  //把值2018赋给变量a

赋值表达式语句的目的是把值储存到内存位置上,用于储存值的数据存储区域统称为数据对象

加法运算符:+

将其左侧的值与右侧的值相加

减号运算符:-

将其左侧的值减去右侧的值

符号运算符:-和+

-作为一元运算符,改变其右侧值的符号,一元运算符只需要一个运算对象

+作为一元运算符,不会改变运算对象的值或符号

除法运算符:/

/左侧的值是被除数,/右侧的值是除数

four = 12.0/3.0;

整数除法和浮点数除法不同。浮点数除法的结果是浮点数,整数除法的结果是整数

整数是没有小数部分的数,在C语言中,整数除法结果的小数部分会被舍弃,这称为截断

整数除法会截断计算结果的小数部分,而不是四舍五入

负整数的运算也是直接丢弃小数部分,这种方法被称为“趋零截断”

混合整数和浮点数计算的结果是浮点数

实际上,计算机不能真正用浮点数除以整数,编译器会把两个运算对象转换成相同的类型

运算优先级顺序:

运算的优先级顺序跟数学运算优先级顺序一样

其他运算符

C语言规定,sizeof返回size_t类型的值,这是一个无符号整数类型,但它不是新类型

C有一个typedef机制,允许为现有类型创建别名

typedef double real;  //创建一个double的别名real
real test;  //声明一个double类型的变量test

C头文件系统可以使用typeof把size_t作为unsigned int或unsigned long的别名。这样在使用size_t类型时,编译器会根据不同的系统替换标准类型

求模运算符:%

求模运算符用于整数运算

求模运算符给出其左侧整数除以右侧整数的余数

递增运算符:++

递增运算符将其运算对象递增1,该运算符有两种方式。

第一种是,++在其作用的变量前面,这是前缀模式

第二种是,++在其作用的变量后面,这是后缀模式

这两种模式递增行为发生的时间不同

x = a++;  //后缀模式,使用了a的值之后才递增a
y = ++b;  //递增了b的值之后才使用b的值

还有递减运算符,跟递增运算符是一样的

如果一个变量出现在一个函数的多个参数中,不要对该变量使用递增或递减运算符

如果一个变量多次出现在一个表达式中,不要对该变量使用递增或递减运算符

表达式和语句

表达式由运算符和运算对象组成,C语言中,每个表达式都有一个值,要想获得这个值,就要根据运算符优先级顺序规定的顺序来执行操作

条件表达式的值为0或1,如果条件为真,表达式的值为1;如果条件为假,表达式的值为0

语句是C程序的基本构建块,一条语句相当于一条完整的计算机指令,但不是所有的指令都是语句,例如x = 6 + (y * 5)

语句可以改变值或调用函数

在C中,大部分语句都以分号结尾

legs = 4  //只是一个表达式
legs = 4; //语句
;            //只有一个分号为空语句,最简单的语句是空语句

C把末尾加上一个分号的表达式都看作是一条语句,即表达式语句,声明不是表达式语句

#include <stdio.h>

int main(void)
{
	int count, sum;              //声明

	count = 0;                   //表达式语句
	sum = 0;                     //表达式语句
	while (count++ < 20)         //迭代语句
		sum = sum + count;
	printf("sum = %d\\n", sum);   //表达式语句

	return 0;                    //跳转语句
}

如果删除声明后面的分号,剩下的部分不是一个表达式,也没有值

int count  //不是表达式,也没有值

在C语言中,赋值和函数调用都是表达式,没有所谓的“赋值语句”和“函数调用语句”,这些语句实际上都是表达式语句

赋值表达式语句在程序中很常用,它为变量分配一个值

赋值表达式语句的结构是,一个变量名,后面是一个赋值运算符,再跟着一个表达式,最后以分号结尾

函数表达式语句会引起函数调用

副作用和序列点

副作用是对数据对象或文件的修改,使用一条语句的主要目的就是使用其副作用

例如,调用printf()函数时,它显示的信息其实是副作用

序列点是程序执行的点,在该点上,所有的副作用都在进入下一步之前发生

在C语言中,语句中的分号标记了一个序列点

在一条语句中,赋值运算符、递增运算符和递减运算符对运算对象做的改变必须在程序执行下一条语句前完成

任何一个完整表达式的结束也是一个序列点

完整表达式就是指这个表达式不是另一个更大表达式的子表达式

复合语句(块)

复合语句是用花括号括起来的一条或多条语句,复合语句也称为块

#include <stdio.h>

int main(void)
{
	int count = 0;
	int sum = 0;

	while (count++ < 10)
		sum = 10 * count +2;
	printf("sum = %d\\n", sum);
}

while循环中只有一条赋值表达式语句,没有花括号,while语句从while这行运行到下一个分号。循环结束后,才执行printf()函数

运行结果

#include <stdio.h>

int main(void)
{
	int count = 0;
	int sum = 0;

	while (count++ < 10)
	{
		sum = 10 * count +2;
		printf("sum = %d\\n", sum);
	}
}

花括号确保两条语句都是while循环的一部分,每执行一次循环就调用一次printf()函数

根据while语句的结构,整个复合语句被视为一条语句

运行结果

类型转换

当类型转换出现在表达式时,无论是unsigned还是signed的char和short都会被自动转换成int,如有必要会被转换成unsigned int(如果short和int的大小相同,unsigned short就比int大,这种情况下,unsigned short会被转换成unsigned int),从较小类型转换成较大类型,这些转换被称为升级

涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别

类型的级别从高到低依次是long double、float、unsigned long long、long long、unsigned long、long、unsigned int、int。例外的情况是,当long和int的大小相同时,unsigned int比long的级别高。short和char类型会被升级到int或unsigned int

在赋值表达式语句中,计算的最终结果会被转换成被赋值变量的类型。这个过程可能导致类型升级或降级。降级就是把一种类型转换成更低级别的类型

当作为函数参数传递时,char和short被转换成int,float被转换成double

类型升级通常都不会有什么问题,但是类型降级会导致一些麻烦,因为较低类型可能放不下整个数字

如果待转换的值是否与目标类型匹配,这取决于转换涉及的类型,待赋值的值与目标类型不匹配时,规则如下:

1.目标类型是无符号整型,且待赋的值是整数时,额外的位将被忽略

2.如果目标类型是有一个有符号整型,且待赋的值是整数,结果因实现而异

3.如果目标类型是一个整型,且待赋的值是浮点数,该行为是未定义的

如果把一个浮点数转换成整数,小数部分会被截断

强制类型转换运算符

通常,应该避免自动类型转换,尤其是类型降级

强制类型转换,即在某个量的前面放置用圆括号括起来的类型名,该类型名即是希望转换成的目标类型

圆括号和它括起来的类型名构成了强制类型转换运算符

int mice;  //定义一个int类型的变量mice
mice = 1.6 + 1.7;  //自动类型转换,1.6+1.7的结果3.3被截断为整数3
mice = int(1.6) + int(1.7);  //1.6和1.7在相加之前被转换成整型(1),把1+1的结果赋给mice

本质上,两种类型转换都好不到哪去,要考虑程序的具体情况再做取舍

带参数的函数

看一个打印指定数量的#号的小程序

#include <stdio.h>

void pound(int n);  //ANSI函数原型声明
int main(void)
{
	int times = 5;
	char ch = \'!\';
	float f = 6.0f;

	pound(times);  //int类型的参数
	pound(ch);     //和pound((int)ch);相同
	pound(f);      //和pound((int)ch);相同

	return 0;
}

void pound(int n)  //表示该函数接受一个int类型的参数
{
	while (n-- > 0)
		printf("#");
	printf("\\n");
}

运行结果

void pound(int n),如果函数不接受任何参数,函数头的圆括号中应该写上关键字void。由于该函数接受一个int类型的参数,所以圆括号中包含一个int类型变量n的声明

声明参数就创建了被称为形式参数(形参)的变量

函数调用传递的值为实际参数,简称实参

形参是变量,实参是函数调用提供的值,实参被赋给相应的形参

函数的原型即是函数的声明,描述了函数的返回值和参数,所以变量ch和f都被转换成int类型

函数名前面有void关键字,该函数没有返回值

以上是关于C Primer Plus学习笔记- 运算符表达式和语句的主要内容,如果未能解决你的问题,请参考以下文章

读书笔记C Primer Plus ch.15位运算 示例程序15.3 定义并使用字段

C++ Primer Plus学习:第六章

C++ Primer 0x04 学习笔记

C++ Primer 0x04 学习笔记

C语言-学习笔记 --《c primer plus》

C Primer Plus学习笔记- C 控制语句:分支和跳转