在我刚开始学C语言的时候,语句和运算符号这些对我来说还是很陌生的。
现在来看我对于这个的理解其实就是一种 处理数据语法的规范,因为计算机处理数据和我们人来处理数据是有不一样的。计算机面对我们现实生活,计算机其实是做了抽象,编程语言就是对处理真实世界的方法提供的一种处理工具,里面的运算符和表达式语句这些都是用编程语言来描述真实世界罢了。
运算符、表达式、语句也是处理数据的语法规范。也就是说编程语言能够处理这种符合规范的语句,在这个语法之外的情况是不能被处理的。就像英语一样,总是按照一定的规则,主谓宾之类的的规则。
把 我们人 类别于 计算机
我们就能明白:一天的时间是24小时。 这个语句的意思
但是我们可能不太明白:24一天是的时间 的语句意思,但即是认识语句,但是很可能误解我们的意图。
计算机也是只能接收合法的规则信息,也就是编程语言编写的有效语句。
编程语言的诞生就是为了方便人类来解决生活的问题。存在的意义就是解放人类,创造价值。解决问题就是需要处理问题,把问题以一定的形式输入到计算机里面成为计算机数据,再用编程语言编写出软件来处理数据,就达到了处理数据的目的啦。
运算符其实就是 C语言对数据进行一种处理的符号,我们可以用这些符号来解决真实世界中的任务。
运算符号和变量常量等等构成的一些式子,也叫运算符表达式和语句,这些就是处理数据的功能,完全是计算的功能。
运算符 总是和参与运算的 运算单元 在一起的。运算符不能单独存在的哈,单独存在就失去其意义啦
就像下面的 j = i + j;
int i = 0, j = 0;
j = i + j;
j = (i + j) * j - j;
解释就像下面
i | + | j |
---|---|---|
运算单元 | 运算符 | 运算单元 |
( | i | + | j | ) | * | j | - | j |
---|---|---|---|---|---|---|---|---|
运算符 | 运算单元 | 运算符 | 运算单元 | 运算符 | 运算符 | 运算单元 | 运算符 | 运算单元 |
这里面就会引出两个问题:
第一个问题其实就是在C语言里面会有这种概念叫 多目运算符 就三种
第二个问题 C语言也有解决的概念叫 运算符优先级
数学符号就是和 我们认知里面的数学是一致的。
int i = 0;
int j = 1;
j = j+i;
j = j-1;
这个就是普通的条件逻辑判断的。
||:或:两个条件满足一个即可
&&:且
==:相等
!:取反
>:大于
>=:大于等于
<:小于
<=:小于等于
!=:不等于
C语言的强大也在于对二进制的支持。像很多时候,数据本身是以二进制的方式存储着,但是我们可以通过二进制的方式去处理数据。
//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::Widget | 0x00000000 |
Qt::Window | 0x00000001 |
Qt::Dialog | 0x00000002 | Window |
Qt::Sheet | 0x00000004 | Window |
Qt::Drawer | Sheet | Dialog |
Qt::Popup | 0x00000008 | Window |
Qt::Tool | Popup | Dialog |
这个其实就是非常的一个便捷运算:
下面两个语句是等效的。下面其实就是对上面的 数学运算符 和 二进制运算符 常用功能的简写。
i = i + 1;
i += 1;
其实就是 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;
此时的 左值和右值 其实是由 赋值号 = 的左右来区分的。
就比如下面的代码中:
int i = -1;
i = 78-11*32(22+24);
对我来理解,表达式目的就是计算出一个值,表达式总是会被计算出一个值出来。而这个值呢?总是会存在左值里面,也就是存在变量里面的。
表达式的意义就是用计算出数据,表达的目的就是计算出一个值出来。
就行 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;
上面知道了 语句分隔的情况,那我们就清楚就是
像上面的 语句都是一个个单语句
int i = 0;
i = i+2;
i += 4;
i *= 6;
用的是 { } 来括起来的
一般就是在像 条件判断、循环、函数体的写法会使用 把 一条条单语句或者 嵌套的语句块 打包在一个作用域
编译器要识别这个条件的作用范围,不然因为 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;
在编译器编译的时候,会去掉源码中的很多东西,会压缩
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;;;