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. java开发---关于ORA00604和ORA12705

    MyEclipse和oracle连接中出现的一个问题: 在使用工具连接orcale数据库时报了这两个异常  ORA-00604和ORA12705 ; 查找问题原因: 大概猜测是与字符集有关系 , 确认 ...

  2. c++小游戏——贪吃蛇

    #include #include #include #include #include <conio.h> #include #include <windows.h> usi ...

  3. 如何在 Centos7 中安装 gcc

    系统环境:Centos7.4 今天在安装 Nodejs8.7 的时候,报了一个警告: WARNING: C++ Compiler too old, need g++ 4.9.4 or clang++ ...

  4. 林大妈的JavaScript基础知识(三):JavaScript编程(1)对象

    1. 对象的简单介绍与一些注意事项 JavaScript中具有几个简单数据类型:数字.字符串.布尔值.null值以及undefined值.除此之外其余所有值(包括数组.函数,甚至正则表达式)都是对象. ...

  5. [POJ2559&POJ3494] Largest Rectangle in a Histogram&Largest Submatrix of All 1’s 「单调栈」

    Largest Rectangle in a Histogram http://poj.org/problem?id=2559 题意:给出若干宽度相同的矩形的高度(条形统计图),求最大子矩形面积 解题 ...

  6. Linux 下实践 VxLAN

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,欢迎大家关注,二维码文末可以扫. 来源:ht ...

  7. bean的创建(五)第二部分 寻找bean的工厂方法实例化

    instanceWrapper = createBeanInstance(beanName, mbd, args); AbstractAutowireCapableBeanFactory.create ...

  8. VisualStudio中的单元测试

    1. VisualStuio中的测试资源管理器.CodeLens和ReSharper 上一篇文章重温了<单元测试的艺术>里提到的单元测试的技术及原则.这篇文章实践使用VisualStudi ...

  9. 输出单链表倒数第K个结点值

    #include<iostream>using namespace std;#include<malloc.h>#include<stdio.h>typedef i ...

  10. java高并发系列 - 第22天:java中底层工具类Unsafe,高手必须要了解

    这是java高并发系列第22篇文章,文章基于jdk1.8环境. 本文主要内容 基本介绍. 通过反射获取Unsafe实例 Unsafe中的CAS操作 Unsafe中原子操作相关方法介绍 Unsafe中线 ...