【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句

发布时间:2023-11-10 13:30

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句

  • 5.1 运算符
    • 算术运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 赋值运算符
    • 杂项运算符 ↦ sizeof & 三元
    • C 中的运算符优先级
  • 5.2 表达式与语句
    • 表达式
    • 语句
    • C 术语:副作用和序列点
    • 复合语句(块)
  • 类型转换
    • 隐式转换
    • 强制类型转换
  • 带参数的函数
    • 形参与实参
    • 函数调用

5.1 运算符

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符,并提供了以下类型的运算符:

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符
  • 杂项运算符

算术运算符

下表显示了 C 语言支持的所有算术运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第1张图片

关系运算符

下表显示了 C 语言支持的所有关系运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第2张图片

逻辑运算符

下表显示了 C 语言支持的所有关系逻辑运算符。假设变量 A 的值为 1,变量 B 的值为 0,则:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第3张图片

位运算符

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:
【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第4张图片
假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:

A = 0011 1100

B = 0000 1101


A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

赋值运算符

下表列出了 C 语言支持的赋值运算符:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第5张图片

杂项运算符 ↦ sizeof & 三元

下表列出了 C 语言支持的其他一些重要的运算符,包括 sizeof 和 ? :。

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第6张图片

sizeof 运算符以字节为单位返回运算对象的大小。C语言规定,sizeof 返回 size_t 类型的值。这是一个无符号整数类型,但它不是新类型。

C 中的运算符优先级

运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。

下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第7张图片

5.2 表达式与语句

表达式

表达式由运算符和运算对象组成。

C 表达式最重要的特性是,每一个表达式都有一个值

语句

语句是 C 程序的基本构建块。一条语句相当于一条完整的计算机指令。

语句可分为简单语句和复合语句。

C 术语:副作用和序列点

副作用是对数据对象或文件的修改。

序列点是程序执行的点,在该点上,所有的副作用都在进入下一步之前发生。在 C 语言中,语句中的分号标记了一个序列点,另外,任何一个完整表达式(这个表达式不是另一个更大表达式的子表达式)的结束也是一个序列点。

复合语句(块)

复合语句是用花括号括起来的一条或多条语句。

类型转换

数据有不同的类型,不同类型数据之间进行混合运算时必然涉及到类型的转换问题。

转换的方法有两种:

  • 自动转换(隐式转换):遵循一定的规则,由编译系统自动完成
  • 强制类型转换:把表达式的运算结果强制转换成所需的数据类型

类型转换的原则:占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低。

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

当把一个浮点数值转换成一个整数类型时,原来的浮点值会被截断。

例如:

/* 类型降级 */
#include 
#include 

int main()
{
    float a = 23.99;
    int b = a;
    printf("%d\n", b); // 打印23,精度丢失

    system("pause");
    return 0;
}

运行结果:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第8张图片

类型的级别从高到底依次是 long double、double、float、unsigned long long、long long、unsigned long、long、unsigned int、int。例外的情况是,当 long 和 int 的大小相同时,unsigned int 比 long 的级别高。

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第9张图片

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

隐式转换

遵循一定的规则,由编译系统自动完成。

例:

#include 
#include 

int main()
{
    float p = 3.14;
    int w = 2;
    // 隐式转换
    float sum = p * w;
    printf("%f\n", sum);

    system("pause");
    return 0;
}

运行结果:
【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第10张图片

强制类型转换

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

圆括号和它括起来的类型名构成了强制类型转换运算符。其通用行式是(type)。

例:

/** 强制类型转换 **/
#include 
#include 

int main()
{
    float p = 4.6;
    int w = 2;

    int sum = (int)p * w;
    printf("%d\n", sum);
    sum = (int)(p * w);
    printf("%d\n", sum);

    system("pause");
    return 0;
}

运行结果:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第11张图片

带参数的函数

程序清单5.15:

/* pound.c -- 定义一个带一个参数的函数 */
#include
void pound(int n); //ANSI函数原型声明
int main(void)
{
	int times = 5;
	char ch = '!'; // ASCII码是33
	float f = 6.0f;

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

    system("pause");
	return 0;
}

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

形参与实参

我们看该程序的函数头:void pound(int n)

声明参数就创建了被称为形式参数的变量,在该例中,形参就是 int 类型的 n。

我们称函数调用传递的值为实际参数,像pound(10)这样的函数调用会把 10 赋给 n。过程为:函数调用pound(10)把实参 10 传递给函数,然后该函数把 10 赋给形参(变量 n)。

变量名是函数私有的,即在函数中定义的函数名不会和别处的相同名称发生冲突。

运行结果:

【《C Primer Plus》读书笔记】第5章:运算符、表达式和语句_第12张图片

函数调用

我们看该程序的函数头:void pound(int n)

原型是函数的声明,描述了函数的返回值和参数。

pound() 函数的原型说明了2点:

  • void 说明该函数没有返回值
  • 该函数有一个 int 类型的参数

该例中,函数原型告诉编译器pound() 需要一个 int 类型的参数。相应地,当编译器执行到 pound(ch)时,会把参数 ch 自动转换成 int 类型。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号