C语言参悟-运算符表达式和语句

一、概述

在我刚开始学C语言的时候,语句和运算符号这些对我来说还是很陌生的。

现在来看我对于这个的理解其实就是一种 处理数据语法的规范,因为计算机处理数据和我们人来处理数据是有不一样的。计算机面对我们现实生活,计算机其实是做了抽象,编程语言就是对处理真实世界的方法提供的一种处理工具,里面的运算符和表达式语句这些都是用编程语言来描述真实世界罢了。

运算符、表达式、语句也是处理数据语法规范。也就是说编程语言能够处理这种符合规范的语句,在这个语法之外的情况是不能被处理的。就像英语一样,总是按照一定的规则,主谓宾之类的的规则。

  • 语法规范

我们人 类别于 计算机

我们就能明白:一天的时间是24小时。 这个语句的意思

但是我们可能不太明白:24一天是的时间 的语句意思,但即是认识语句,但是很可能误解我们的意图。

计算机也是只能接收合法的规则信息,也就是编程语言编写的有效语句。

  • 处理数据

编程语言的诞生就是为了方便人类来解决生活的问题。存在的意义就是解放人类,创造价值。解决问题就是需要处理问题,把问题以一定的形式输入到计算机里面成为计算机数据,再用编程语言编写出软件来处理数据,就达到了处理数据的目的啦。

二、运算符

运算符其实就是 C语言对数据进行一种处理的符号,我们可以用这些符号来解决真实世界中的任务。

运算符号和变量常量等等构成的一些式子,也叫运算符表达式和语句,这些就是处理数据的功能,完全是计算的功能。

0. 运算符分类

运算符 总是和参与运算的 运算单元 在一起的。运算符不能单独存在的哈,单独存在就失去其意义啦

就像下面的 j = i + j;

int i = 0, j = 0;

j = i + j;
j = (i + j) * j - j;

解释就像下面

i+j
运算单元运算符运算单元
(i+j)*j-j
运算符运算单元运算符运算单元运算符运算符运算单元运算符运算单元

这里面就会引出两个问题:

  • 一、1个运算符能够和几个 运算单元 组合
  • 二、运算符 之间 共用 运算单元 的时候 是谁先算呢?
  • 三、计算的顺序呢?-》这个一般就是从左到右计算的,

第一个问题其实就是在C语言里面会有这种概念叫 多目运算符 就三种

  • 单目运算符:++;- - 就是一个运算符 与 一个运算单元组合 -》 1 对 1
    就像 i++, i- -
  • 双目运算符:+ ;-;*;/;% 就是一个运算符 要和 两个运算单元组合 -》1 对 2
  • 三目运算符:? : 就是一个运算符 要和 三个运算单元组合 -》1 对 3

第二个问题 C语言也有解决的概念叫 运算符优先级


下面的表格其实就是 对 C语言里面所有的运算符的介绍。
在这里插入图片描述

1. 数学运算符

数学符号就是和 我们认知里面的数学是一致的。

  • +:加号
  • -:减号
  • *:乘号
  • /:除号
  • %:取余号
  • =:赋值号:就是把右边的值赋给昨天的值
    这个比较特殊,可以放在语句后面
int i = 0;
int j = 1;

j = j+i;
j = j-1;

2. 逻辑运算符

这个就是普通的条件逻辑判断的。

  • ||:或:两个条件满足一个即可

  • &&:且

  • ==:相等

  • !:取反

  • >:大于

  • >=:大于等于

  • <:小于

  • <=:小于等于

  • !=:不等于

3. 二进制运算符

C语言的强大也在于对二进制的支持。像很多时候,数据本身是以二进制的方式存储着,但是我们可以通过二进制的方式去处理数据。

  • <<、 >> 移位运算符
    对于左移、右移,体现在二进制的位数-总是在 2 的倍数扩大或缩小,左右移都会溢出位数,就是都会变成0的。这个要小心点。
//0000 1000
int i = 8;

//左移一位
i = i << 1;	// i  == 0001 0000 变成 16了

//右移一位
i = i >> 1;	// i  == 0000 0100 变成 4了
  • 二进制与或非异或
int i = 1;	// 0000 0001
int j = 2;	// 0000 0010
int k = 4;	// 0000 0100

int m;

//或运算 就是为了取并集
m = i | j; // 0000 0011
m = i | k; // 0000 0101

//与运算 就是为了取交集
m = 1 & 3;	// 0000 0001 & 0000 0011 == 0000 0001
m = 5 & 3;	// 0000 0111 & 0000 0011 == 0000 0011

//非运算 就是为了 0 和 1交替
m = ~3;	// ~0000 0011 == 1111 1100
m = ~4;	// ~0000 0100 == 1111 1011

//异或预算 就是为了 或的逆运算
m = 1 ^ 3;	// 0000 0001 ^ 0000 0011 == 0000 0010
m = 5 ^ 3;	// 0000 0111 & 0000 0011 == 0000 0100

这个不太懂的话,可以看看二进制的运算规则,C语言也是提供了这样的一个语法功能。

这个在底层代码即是直接设置 16进制的值比较多,就像51单片机点灯的时候,把一个16位的数映射到8个IO口一样。

但是在 上层应用开发的时候,常常会用二进制的运算当成参数和功能的累计。

就像下面的一个API函数一样,Qt::WindowFlags 可以用二进制的方式进行参数累计

setWindowFlags(Qt::WindowFlags type)

我们就可以用 | 运算符去并集参数。就是兼济多个参数的功能,我们解析这些参数的时候用 ^ 就可以逆运算回去。

setWindowFlags(Qt::Dialog | Qt::Widget)
WindowFlags 参数名功能
Qt::Widget0x00000000
Qt::Window0x00000001
Qt::Dialog0x00000002 | Window
Qt::Sheet0x00000004 | Window
Qt::DrawerSheet | Dialog
Qt::Popup0x00000008 | Window
Qt::ToolPopup | Dialog
  • >>:右移
  • <<:左移
  • &:与
  • |:或
  • ~:非
  • ^:异或

4. 便捷组合运算符

这个其实就是非常的一个便捷运算:

下面两个语句是等效的。下面其实就是对上面的 数学运算符二进制运算符 常用功能的简写。

i = i + 1;

i += 1;
  • +=:
  • *=
  • /=
  • %=
  • ^=
  • &=
  • |=
  • >>=
  • <<=

5. ++ - - 运算符

其实就是 i++ 和 i- - 这种功能。因为这个运算符和操作数的位置不一样的话,还是有些区别的。

主要是用在流程控制上。

主要是在赋值上。

i++ 的流程就是 ,如果 i 需要给其他值赋值的话,就先赋值,然后再 自增加 1
++i 的流程就是 ,如果 i 需要给其他值赋值的话,就先 自增加 1,然后赋值
一样的 i- -、- - i 也是这样工作的。

int k = 0;
int res = -1;

res = k++;	//此时先赋值 k 值到res; res 值是 0; k 自增为 1
res = ++k;  //此时先 k 先自增为 2; 然后再赋值给res;  res 值是 2; 

三、表达式

1. 左值、右值

此时的 左值和右值 其实是由 赋值号 = 的左右来区分的。

就比如下面的代码中:

int i = -1;
i = 78-11*32(22+24);
  • i : 左值
    左值:可读可写
    左值的角色基本上就只能是变量,就是一个作为被赋值的对象,
  • 78-11*32(22+24):右值
    右值:只读不写
    右值是不会出现在赋值号左侧的,右值只是计算出一个值,然后存储在左值里面
    右值一般是计算出来的,当然也是可以直接给值的。

2. 表达式

对我来理解,表达式目的就是计算出一个值,表达式总是会被计算出一个值出来。而这个值呢?总是会存在左值里面,也就是存在变量里面的。

表达式的意义就是用计算出数据,表达的目的就是计算出一个值出来。

就行 if 里面的条件也是表达式 计算出来的就是一个 0 或者 非 0

if(2 < 3 && 3 > 4)
{
	//....
}

也比如下面的 getChar() 函数计算出的其实 就是一个 char 类型的值。

char ch = getChar();

可见 C语言的设计者真的设计的非常好!

四、语句

语句总是用 ‘;’ 分隔开的,因为 C语言的执行顺序,总是沿着代码从上往下执行,执行就得一步一步走。

这方便我们把复杂的任务流程化、分解化,大事化小,小事化了。

也就是按照 line 1 、line 2、line 3、line 4、line 5 一步一步执行,那怎么把这一步一步分解呢?

就是用的 ‘;’ 表示 ‘一步’,用这个来分解的。语句其实就是把表达式分隔的一种功能。我习惯把表达式加上 ‘;’ 结尾的称为语句

line 1-> int i = 0;
line 2->
line 3-> i = i+2;
line 4-> i += 4;
line 5-> i *= 6;

当然,并不是说 只能换行就是语句的分隔符哈,这样也是有效的,也是按照分隔符号的位置从上往下执行的,换行写只是为了方便人阅读方便。

int i = 0;i = i+2;i += 4;

i *= 6;

1. 单语句

上面知道了 语句分隔的情况,那我们就清楚就是

像上面的 语句都是一个个单语句

int i = 0;
i = i+2;
i += 4;
i *= 6;

2. 语句块

用的是 { } 来括起来的

一般就是在像 条件判断、循环、函数体的写法会使用 把 一条条单语句或者 嵌套的语句块 打包在一个作用域

编译器要识别这个条件的作用范围,不然因为 C语言总是从上往下执行的,有时候就得界限这个条件的范围,不然会没有执行代码的边界。

C语言最讨厌没有边界感的人 在这里插入图片描述

  • (正常括号)
if (1)
{
	int i = 0;

	i = i+2;
	i += 4;
	i *= 6;
}

就行如果没有标志的话,不定义 大括号,像if while 都会把 最近的 ‘;’ 作为自己的作用域。

  • (不带括号)
if (1)

	int i = 0;

	i = i+2;
	i += 4;
	i *= 6;

这个其实就是等价于,我们明显想要if包括四个语句的,不带括号是明显不满足我们的要求

if (1)
{
	int i = 0;
}
i = i+2;
i += 4;
i *= 6;

3. 空语句

在编译器编译的时候,会去掉源码中的很多东西,会压缩

if (1)
{
	int i = 0;

	i = i+2;
	i += 4;
	i *= 6;
}

压缩成这种,很多换行符都没有的啦,就是用的 ‘;’ 和 { } 分隔的

if (1){int i = 0;i = i+2;i += 4;i *= 6;}

空语句就是,没有表达的 但是带了 ‘;’ { } 这种的,没事问题

if (1)
{}

int i;;;

4. 三元运算符

  • 判断条件 ? 真值语句1 : 假值语句2

三元运算符有时候非常有用,他结合了 if else 的功能,但是写法却是简洁的优美

在执行完 判断条件 后的值,如果是真值则执行 真值语句1 ,假值则执行 假值语句2

我经常在条件输出的时候使用

cout<< (3 >4 ? string("3>4 true") : string("3>4 false"));
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳风暴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值