C4 运算符、表达式和语句

C通过运算符提供多种操作。每个运算符的特性包括运算对象的数量、优先级和结合律。当两个运算符共享一个运算对象时,优先级和结合律决定先进行哪项运算。每个C表达式都有一个值。

虽然C会自动进行类型转换,但不应依赖,应该显式使用合适的类型或使用强制类型转换。

1. 基本运算符

C用运算符(operator)表示算数运算。

基本运算符=+-*

1.1 赋值运算符=

使用=可以将一个值赋给一个变量。

count = 0;
author = "Caldm";
apple_price = 1000;

赋值运算符的左侧必须是引用一个存储位置。最简单的方式是使用变量名。

数据对象、左值、右值和运算符

用于储存值的数据存储区域统称为数据对象data object)。

左值lvalue)用于标识特定数据对象的名称或表达式。

对象指的是实际的数据存储,而左值是用于标识或定位存储位置的标签。

右值rvalue)指的是能赋值给可修改左值的量,且本身不是左值。

1.2 加法运算符:+

加法运算符(addition operator)用于加法运算,将两侧的值相加。

1.3 减法运算符:-

减法运算符(subtraction operator)用于减法运算,将两侧的值相减。

1.4 符号运算符:-+

减号可以用于标明一个值的代数符号。如:

rocky = -12;
smokey = -rocky;

以这种方式使用的负号被称为一元运算符unary operator)。

C90新增+,它不会改变对象的值或符号。

dozen = +12;

这在以前是不允许的。

1.5 乘法运算符:*

乘法运算符用于乘法运算,用于将两侧的数相乘。

1.6 除法运算符:/

除法左侧的值是被除数,右侧的值是除数。

在C语言中,整数除法和浮点数除法不同。

整数除法的结果是整数,其小数部分会被丢弃,这个过程被称为截断truncation

5 / 3; // 结果为1,而不是1.666...

浮点数除法的结果是浮点数。

1.7 运算符优先级

运算符优先级(从高到低)

运算符结合律
()从左往右
+ -(一元)从右往左
* /从左往右
+ -(二元)从左往右
=从右往左

2. 其他运算符

2.1 sizeof运算符和size_t类型

sizeof运算符以字节为单位返回对象的大小。在C中,以char类型的大小作为1字节,char类型的大小通常为8位,但一些字符集可能使用更大的字节。

sizeof返回的数据是size_t类型,这是一个无符号整数类型,但size_t类型不是新的类型,而是通过typedef定义的类型别名。

比如这里的size_t类型实际上是unsigned long long类型。

2.2 求模运算符:%

求模运算符modulus operator)用于整数运算。

2.3 递增运算符:++

递增运算符(increment operator)将其运算对象递增1。

前缀模式:++i,先对i进行递增,再用i的值进行表达式的计算。

int i = 2;
a = 2 + ++i; // a = 5

后缀模式:i++,先使用i的值进行表达式的计算,再对i进行递增

int i = 2;
a = 2 + i++; // a = 4

2.4 递减运算符:--

递减运算符(decrement operator)将其运算对象递增1

递减运算符也有前缀模式和后缀模式,规则与递增运算符的相同。

3. 表达式和语句

3.1 表达式

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

每个表达式都有一个值。要获取这个值,就必须根据运算符的优先级规定的顺序执行操作。

3.2 语句

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

副作用和序列点

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

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

3.3 复合语句

复合语句(compound statement)是用花括号括起来的一条或多条语句,复合语句也被称为块(block)。

4. 类型转换

在语句和表达式中通常应该使用类型相同的变量和常量,如果使用混合类型,则会根据规则自动进行类型转换。

  • 升级:类型从低转换到高。
  • 降级:类型从高转换到低。
  1. 当类型转换出现在表达式中时,有无符号的charshort都会被转换为int,有必要时还会转换为unsigned int
  2. 涉及两种类型的运算,两个值会被分别转换为两种类型的更高级别
  3. 类型的级别从高到低依次为:long doubledoublefloatunsigned long longlong longunsigned longlongunsigned intint。当longint大小相同时,unsigned int会大于long
  4. 在赋值表达式语句中,计算结果会被转换为被赋值变量的类型,这可能导致升级或降级。
  5. 当作为函数参数进行传递时,charshort被转换为intfloat被转换成double

当遇到降级时:

  1. 目标类型是无符号整型,且待赋值的值是整数时,额外的位将被忽略。
  2. 如果目标类型是一个有符号整型,且待赋的值是整数,结果因实现而异。
  3. 如果目标类型是一个整型,且待赋的值是一个浮点数,原来的浮点值会被截断。

5. 强制类型转换运算符

语法:圆括号和它括起来的类型

(type)

6. 带参数的函数

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

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