Skip to content

语句

在C语言中,表达式和语句是构成程序的基本元素。本节和下一章节我们就围绕它们展开讲一讲其中的C语言基础语法。

首先,让我们区分这两个概念:

  1. ,语句是代码中的一个完整的,可以执行的步骤。
    • 语句的作用复杂多样,常用于构建程序逻辑,如循环语句、条件判断语句、跳转语句等。
  2. ,表达式是由变量、常量(称之为操作数)运算符(也叫操作符)组成的序列,

    • 表达式可以非常简单,如一个单独的常量或变量,或者非常复杂,如包含多个运算符和函数调用的组合。

    • 表达式的作用就是计算值、赋值、函数调用等。

在C语言中,语句和表达式实际上并没有明显的绝对界限,它们的关系是:

  1. 任何表达式只要直接加上一个分号,立刻就会成为一条语句。比如a = 10是一个赋值表达式,但只要加上";",就会变成一个赋值语句。表达式语句是语句最简单的形式。
  2. 语句不仅限于表达式,比如选择、循环等语句,语句可以更多的影响程序的逻辑。

在表达式中,最重要、最核心的就是连接表达式中常量、变量的运算符了,所以本小节我们主要研究C语言的运算符。

C 语言拥有异常丰富的运算符,比较常见和常用的有以下运算符:

  1. 算术运算符
  2. 赋值运算符
  3. 关系运算符
  4. 逻辑运算符
  5. 位运算符
  6. 三目运算符

这些运算符,又可以根据操作数的多少,分为:

  1. 一元运算符,只需要一个操作数的运算符
  2. 二元运算符,需要两个操作数的运算符,多数运算符都属于二元运算符。
  3. 三目运算符,自然就是需要三个操作数的运算符。

下面逐一学习一下。

表达式

C 语言的一个特点就是它更多地强调表达式而不是语句。表达式是用来计算某个值的公式;最简单的表达式就是变量和常量。表达式可以用运算符进行连接,从而创建出更复杂的表达式,比如 a + (b * c)。

C 语言拥有异常丰富的运算符:算术运算符,赋值运算符,关系运算符,判等运算符,逻辑运算符,位运算符...

C 语言有一条不同寻常的规则,那就是任何表达式都可以用作语句。换句话说,不论表达式是什么类型,计算什么结果,我们都可以通过在后面添加分号将其转换成语句。例如,我们可以这样将表达式 ++i 转换成语句:

cpp
++i;

执行这条语句时,首先会计算表达式++i 的值,之后这个值会被丢弃,然后执行下一条语句。

表达式是C/C++中产生值的语句。表达式可以包含常量、变量、操作符和函数调用。

操作符是一种操作,它作用于一个或多个值并产生一个新值。C/C++ 中有许多不同的操作符,包括:

  • 算术运算符:+-*/%
  • 关系运算符:==!=<><=>=
  • 逻辑运算符:&&||!
  • 位运算符:&|^~<<>>

函数调用

函数调用是一种调用函数并执行其代码的方式。函数调用包含函数名及其参数(如果需要)。例如:

cpp
cout << "Hello, world!" << endl;

表达式类型

表达式可以是不同类型的:

  • 整型表达式:产生整数值的表达式。
  • 浮点表达式:产生浮点值的表达式。
  • 字符表达式:产生字符值的表达式。
  • 字符串表达式:产生字符串值的表达式。
  • 布尔表达式:产生布尔值的表达式(true 或 false)。

表达式求值

表达式按优先级从左到右求值。优先级由操作符的类型决定。括号可以用来覆盖优先级。

例如,以下表达式的求值为 10:

cpp
10 + 5 * 2

因为乘法操作符(*)的优先级高于加法操作符(+)。

示例

以下是一些表达式示例:

  • x + y:加法表达式
  • a == b:关系表达式
  • !c:逻辑表达式
  • (x & y) << 2:位运算表达式
  • sqrt(x):函数调用表达式

重要提示

  • 表达式可以嵌套在其他表达式中。
  • 表达式可以作为语句的一部分或作为函数调用的参数。
  • 表达式的类型必须与它所在上下文的预期类型兼容。

表达式的主要作用和副作用

为了更好的描述C语言当中运算符组成的表达式作用,我们引入两个重要的概念:

  1. 表达式的主要作用。表达式的一个特点就是必然会得到一个结果,
  2. 表达式的副作用。比如说:
    1. 修改了变量的值(最常见的)
    2. 执行了某些I/O操作,如打印到控制台或从文件读取数据。
    3. 调用函数,函数中执行了一些操作
    4. ....

举几个例子:

比如表达式5 + 2,其主要作用是计算得出了一个结果值,也就是7,当然它没有副作用。

但假如是表达式int x = 7在这个表达式中就是7。赋值表达式显然是有副作用的,副作用就是改变了变量x的值。

函数调用也是一个典型的表达式,比如test(),假如这次函数调用返回值是100,那么这个表达式的主要作用就是100这个返回值。再假如函数内部进行了I/O操作,将数据打印到了屏幕上,那么I/O操作就是表达式的副作用。

副作用是表达式非常重要的一个效果,它使得表达式可以进行计算值之外的操作,这在很多时候都是非常有用的。

但过于依赖副作用也会导致程序的执行具有更多的不可预测性,使得代码可读性下降,比如:

cpp
int arr[] = {1, 2, 3, 4, 5};
int i = 0;
while (i < 5) {
    printf("%d ", arr[i++]);  // 这行代码的执行需要依赖i++的副作用
}

循环控制变量i的增加,就需要依赖i++的副作用,这无疑增加了复杂性,降低了可读性。如果改成下面:

cpp
printf("%d ", arr[i]);
i++;

代码可读性明显更好。