5.3.5 和二进制极为密切的运算符

  本小节的运算符需要借助二进制概念来理解。

  二进制数据中,比如一个字节的数据,它的十进制为228,二进制就为11100100,如图5.11,

  注意:如果不懂怎么转换十进制和二进制,可以借用windows的计算器来辅助。

图5.11  228的十进制和二进制表现

  把 11100100 整体往右边挪动一位,就会变为01110010。如果觉得不好理解?请这么想,有一条火车轨道,轨道只有八节,一列无限长的火车在这八节轨道上来回移动,如图5.12所示,

图5.12  想象出的场景1

  火车启动前,在轨道上对应的车厢上标有一串数字 11100100,没有对应的车厢统一设数字为0,如图5.13,

  

图5.13  想象出来的场景2

  当火车往右移动一格的时候,在轨道上车厢显示的数据就为 01110010,当火车往右移动两格的时候,轨道上车厢显示的数据就为00111001。

   以上就是数据右移的表现,同理,数据左移就好比刚才那列火车向左移动,总之八节轨道上的车厢只能显示8个数字。

   再看看十进制的228,二进制为11100100,右移一位变为01110010,十进制值为114,在C语言中有移位运算符 >> 和 << 专门用来让数据移位,如下代码,

#include <stdio.h>

void main()
{
unsigned char a = ;
unsigned char b = ; b = a >> ; printf("b = %d\n", b);
}

  运行结果是:b = 114。

  注意:C语言printf不能显示二进制数据,只能显示十进制,十六进制和八进制的数。

  >> 就是右移运算符, << 就是左移运算符。

  读者可以把上述代码的 >> 改为 << ,向左移动一位就会使得 11100100 变为 11001000 ,十进制的值就为200。如果移动2位结果又是怎样呢,读者可以自行脑补。

  上述案例用的是 unsigned char 无符号的字符型数据,它的取值范围是 0~255,所以不管怎么移动,这个数据都是在 0~255 范围内。如果数据是unsigned int 类型,那么这列火车的轨道就要加长到32节,数据就会在 0~4294967295 之内浮动。

  难点来了,如果类型是带负号的 char 型呢?首先它的范围只可以在 -128~127 之间,那就随机选一个数来研究,比如选124,同样是刚才那份代码,将unsigned除去,将 a = 228 改成 a = 124。

  a右移一位运行结果:b = 62,a 左移一位运行结果: b = -8 。这些都与计算机存储数据方式有关,八个字节中,第一位是符号位,如果是0表示符号为正,如果是1表示符号为负,因为笔者写文章动力不足,所以笔者打算不讨论这块,希望读者自行去了解这块知识,可以借助windows的计算机结合写代码来分析有符号的数据移位规律是怎样的。

  

  下一个讲位运算,&, |  , ^,~

  按位与运算&,看起来很熟悉吧,感觉就是取地址符号一样,在运算表达式中它的作用是将左边的数据与右边的数据进行与的运算,与运算就是把每个对应的位进行比对,如果都为1这个位就设置为1,如果不相等或者都为0这个位就设置为0,如图5.14,

  

图5.14  与运算案例

  取二进制数 01011011 同 10011001 进行与运算,结果为 00011101,与运算规则正是遵循了同位都为1取1,其它情况取0,代码如下:

#include <stdio.h>

void main()
{
unsigned char a = ;
unsigned char b = ;
unsigned char c = ; c = a & b; printf("c = %d\n", c);
}

   运行结果:c = 25,十进制数25,它的二进制恰好就为图5.14所运算的结果为 00011001。

    同理,按位或运算 | ,就是左边和右边两个数的每一位进行比对,如果有一个位是1就取1,其它取0。

异或运算 ^ ,左边和右边两个数的每一位进行对比,如果相同取0,不同取1。

     非运算 ~ ,上面三个运算有左边的数和右边的数,非运算只针对一个数进行运算,就是将这个数的每一位都取反,也就是如果是0就取1,如果是1就取0。

   最后讲解比较常用的逻辑运算符 &&, ||, !

    逻辑与 && ,返回的是bool值,也就是返回true或者false,用法如下代码:

#include <stdio.h>
#include <stdbool.h> void main()
{
int a = ;
int b = ;
int c = ;
int d = ;
bool e = false; e = ((a > b)&&(c > d)); printf("e = %d\n", e);
}

  运行结果:e = 1。

  逻辑与 && 是用来连接表达式,表达式的结果是bool 值,好比上述例子,a > b 是true,c > d 是true,所以 true && true 的结果是true,得到 c 的值就为1。读者可以自行修改,比如把 a > b 改为 a < b 得到的 c 是 false && true ,结果是false。所以逻辑与 && 只有三种可能两种结果(不是true就是false):true && true 为 true,true && false 为 false, false && false 为 false。

同理,逻辑或 || ,true || true 为 true,true || false 为 true,false || false 为 false。

   逻辑非 !,加在表达式前,如果数值为0,结果为1;如果数值不为0,结果为0。可以参考以下代码,

  

#include <stdio.h>
#include <stdbool.h> void main()
{
int a = ;
int b = ;
int c = -;
int d = ; d = !a;
printf("d = %d\n", d); d = !b;
printf("d = %d\n", d); d = !c;
printf("d = %d\n", d);
}

  运行后,d的值分别为:0,1,0。

最后的最后讲解一个非主流的运算符 sizeof  。

   C语言学到后期,一般都会误认为 sizeof 是个C库的函数,其实它是个运算符,用于计算变量或者字符串占用内存的字节数,代码如下:

  

#include <stdio.h>
#include <stdbool.h> void main()
{
int a = ;
char b = ;
float c = 3.1415;
bool d = false;
int result = -; result = sizeof(a);
printf("result = %d\n", result); result = sizeof(b);
printf("result = %d\n", result); result = sizeof(c);
printf("result = %d\n", result); result = sizeof(d);
printf("result = %d\n", result);
}

  运行结果 result 的值依次为:4,1,4,1。这个结果刚好就是一个整型int占用字节数4,一个char占用字节数1,一个float占用字节数4,一个bool占用字节数1。

5.4 变量命名法

  本节最后讲解两种变量的命名方式,之前变量命名由于代码比较短小,很容易就能理解代码的意思,所以随便用个a或者b就凑合着用了,但是如果要用C语言做个大一点的项目,也就是当代码量很大的时候,变量名就需要人性化一些,便于多人一起维护项目,就像学生写作文一样,评卷老师看到字写得好看,不管内容如何,先给50分。

5.4.1 匈牙利命名法

   参考链接:

  https://baike.baidu.com/item/%E5%8C%88%E7%89%99%E5%88%A9%E5%91%BD%E5%90%8D%E6%B3%95/7632397?fr=aladdin

  

  比如我要给的年龄的变量命名,首先采用的是 int 类型,在匈牙利命名规则中,整型一般用 i 或者 n ,所以这么声明变量:

int nAge;

5.4.2 其它命名法

  笔者在 linux 驱动代码中选取了一个比较有代表性的变量命名:

  注意:linux 驱动代码几乎都是用C语言完成的,驱动是用来驱动设备的,C语言在这方面有它的优越性,比如位运算,指针操作等等。

int input_devices_state;

  一看就能明白这个变量的意义,表示输入设备的状态。

bool mutex_acquired;

  这个是互斥锁请求,不明白单词的意思可以用翻译软件。

int retval = ;

  ret 意思为 return ,val 意思为 value,组合起来 retval 就是返回值的意思,后续学函数就能明白返回值的作用了。

  本章终于完结!下一章节讲解的是控制语句,能用C语言做的事情多起来了!

C语言编程入门之--第五章C语言基本运算和表达式-part4的更多相关文章

  1. C语言编程入门之--第五章C语言基本运算和表达式-part1

    导读:程序要完成高级功能,首先要能够做到基本的加减乘除.本章从程序中变量的概念开始,结合之前学的输出函数和新介绍的输入函数制作简单人机交互程序,然后讲解最基础的加减法运算,自制简单计算器程序练手. 5 ...

  2. C语言编程入门之--第五章C语言基本运算和表达式-part2

    5.1.4 再来一个C库函数getchar吸收回车键 回车键也是一个字符,在使用scanf的时候,输入完毕要按下回车键,这时候回车键也会被输入到stdin流中,会搞乱我们的程序. 注意:stdin是输 ...

  3. C语言编程入门之--第五章C语言基本运算和表达式-part3

    5.3  挑几个运算符来讲 常用的运算符除了加减乘除(+-*/)外,还有如下: 注意:以下运算符之间用逗号隔开,C语言中也有逗号运算符,这里不讲逗号运算符. 1. 赋值运算符 =,+=,*= 2. 一 ...

  4. C语言编程入门之--第四章C语言基本数据类型

      导读:C语言程序中经常涉及一些数学计算,所以要熟悉其基本的数据类型.数据类型学习起来比较枯燥,不过结合之前的内存概念,以及本节的字节概念,相信数据类型也就不难理解了.本章从二进制的基本概念开始,然 ...

  5. C语言编程入门之--第六章C语言控制语句

    导读:本章带读者理解什么是控制语句,然后逐个讲解C语言常用的控制语句,含有控制语句的代码量多起来后就要注意写代码的风格了,本章末节都是练习题,大量的练习才能掌握好控制语句的使用. 6.1 什么是控制语 ...

  6. C语言编程入门之--第三章编写第一个C语言程序

    第三章 编写第一个C语言程序 导读:一般学一门计算机语言的第一堂上机课(“上机”顾名思义,上了计算机),就是往屏幕输出“hello world”,本章也不例外. 1.1 Hello,World! 这一 ...

  7. C语言编程入门之--第一章初识程序

    第一章 初识程序 导读:计算机程序无时不刻的影响着人类的生活,现代社会已经离不开程序,程序的作用如此巨大,那么程序到底是什么呢?本章主要讨论程序的概念,唤起读者对程序的兴趣,同时对C语言程序与其它语言 ...

  8. linux 操作系统下c语言编程入门

    2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理  ...

  9. VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)

    上一节中鸡啄米讲了定时器Timer的用法,本节介绍下文件操作类CFile类的使用. CFile类概述 如果你学过C语言,应该知道文件操作使用的是文件指针,通过文件指针实现对它指向的文件的各种操作.这些 ...

随机推荐

  1. .NET CORE上传文件到码云仓库【搭建自己的图床】

    .NET CORE上传文件到码云仓库[搭建自己的图床] 先建一个公共仓库(随意提交一个README文件或者.gitignore文件保证master分支的存在),然后到gitee的个人设置页面找到[私人 ...

  2. Linux版本划分——基于打包方式

    基于Dpkg (Debian系) Debian GNU / Linux是一种强调使用自由软件的发行版.它支持多种硬件平台.Debian及其派生发行版使用deb软件包格式,并使用dpkg及其前端作为包管 ...

  3. C#程序从Excel表格中读取数据并进行处理

    今天做了一个Excel表格数据处理的事情,因为数据量表较大(接近7000条)所以处理起来有点麻烦,于是写了一个程序, 先将程序记下以便将来查找. using System; using System. ...

  4. Java用户程序

    Java的用户程序分为两类:Java Application和Java Applet. 这两类程序在程序结构和执行机制上有一定的差异. Java Application是完整的程序,需要独立的Java ...

  5. kubernetes二进制高可用部署实战

    环境: 192.168.30.20 VIP(虚拟) 192.168.30.21 master1 192.168.30.22 master2 192.168.30.23 node1 192.168.30 ...

  6. IOS应用无法下载、此时无法安装应用程序

    无法安装应用 app开发者,进行程序测试,重试还不行,就重新打包, 个人,更改wifi的dns 在“设置” –> “WiFi” –> 进入当前的WiFi 进入之后点击旁边的叹号,然后进入之 ...

  7. Chrome 跨域 disable-web-security 关闭安全策略

    谷歌浏览器暂时关闭跨域. 当遇到以下情况,则可以简单的使用 关闭Chrome 安全策略跨域 开发时跨域,上线后,部署在一个域名下没有跨域问题 开发时,临时解决跨域问题 只有开发时用这个,其他时候,就不 ...

  8. Java1.8新特性实战

    public class JDK8_features {private ArrayList<Integer> list; @Testpublic void test(){/*** 1.La ...

  9. OOM和JVM配置优化

    OOM这个缩写就是Java程序开发过程中让人最头痛的问题:Out of Memory.在很多开发人员的开发过程中,或多或少的都会遇到这类问题,这类问题定位比较困难,往往需要根据经验来判断可能出现问题的 ...

  10. MapReduce 运行全过程解析

    关注公众号,大家可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料. 前言 前面我们讲了 MapReduce 的编程模型,我们知道他主要分成两大阶段来完成一项任务,一是 m ...