首页 > 其他分享 >操作符详解(完)

操作符详解(完)

时间:2023-02-14 22:33:24浏览次数:44  
标签:return int ++ 详解 操作符 printf main

在前面的文章里,已经对基本上大概所有的操作符都进行了讲解,本章主要针对之前未曾讲解过的,以及一些博主认为很重要的进行讲解。

移位操作符

移位操作符一共有两个,一个是左移操作符:<<,一个是右移操作符:>> 他们两个很好区分,看箭头指向的方向,指向左就是左移操作符,指向右,就是右移操作符。

我们还要知道,移位移动的是什么,其实移动的就是一个整数的二进制位

首先我们要知道一个整数的二进制位怎么表示。我们日常见到的数,都是以十进制的形式表现出来的,即用0-9来表示,而在二进制里,只能用0和1来表示一个整数,大家看如下图形就很好理解了:

操作符详解(完)_操作符

再举两个例子:

操作符详解(完)_整型_02

了解这个二进制的转化后,我们接下来了解什么是原码、反码、补码

刚刚我们转化过来的就是这个数的原码,而正数的原码、反码、补码都是相同的

操作符详解(完)_#include_03

正数 原、反、补相同 负数 反码:原码的符号位不变,其余取反 补码:反码+1

移位操作符就是移动的补码

左移操作符<<:左边丢弃,右边补0。看实例:

#include<stdio.h>
int main()
{
int a=4;

printf("%d", a<<1);
return 0;
}

操作符详解(完)_操作符_04

讲解:

操作符详解(完)_操作符_05

如果是负数,就要先求出它的补码,再<<,且听详细分析:

#include<stdio.h>
int main()
{
int a=-4;

printf("%d", a<<1);
return 0;
}

操作符详解(完)_整型_06

讲解:

操作符详解(完)_操作符_07

接下来我们看右移操作符 >> 右移操作符又分为逻辑右移和算数右移 逻辑右移:右边丢弃,左边补0 算数右移:右边丢弃,左边补原符号位(编译器一般都是算术右移)

#include<stdio.h>
int main()
{
int a=4;

printf("%d", a>>1);
return 0;
}

操作符详解(完)_整型_08

负数也同理。

位操作符

&:按位与|:按位或^:按位异或

&:按位与——对应的二进制,有0则为0,两者为1则为1。具体什么意思呢?看如下案例:

#include<stdio.h>
int main()
{

printf("%d", 4 & 5);
return 0;
}

操作符详解(完)_整型_09

最终结果还是4.

|:按位或——只要有1,对应二进制则为1,两者为0则为0

这次举个负数的案例:

#include<stdio.h>
int main()
{

printf("%d", -4 | 5);
return 0;
}

操作符详解(完)_#include_10

^:按位异或——相同为0,相异为1

#include<stdio.h>
int main()
{

printf("%d", -4 ^ 5);
return 0;
}

操作符详解(完)_#include_11

练习题

题目:写一个函数返回参数二进制中 1 的个数。

思路:我们知道1的二进制位只有最右一位为1,其余都是0,假如这个数是a,我们上面学过了,&只有两者同时为1得到的二进制才为1,那假如我们用a的最右位按位与1,由于1的其余位都是0,所以只有最右位为1时得到的才是1,然后我们再把a右移,循环32次,把得到结果为1的统计起来就可以了

代码如下:

#include<stdio.h>
int cont_bit(int a)
{
int cont = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (1 == (a & 1))
{
cont++;
}
a >>= 1;
}

return cont;
}

int main()
{
int a = 0;
scanf("%d", &a);
int cont = cont_bit(a);

printf("%d", cont);
return 0;
}

我们上面知道100的二进制位右有3个1,这个代码能不能实现呢?

操作符详解(完)_操作符_12

可以看出确实如此。这种方法是最容易想到的,也很好理解,当然还有其它方法,在这里就不一一讲解了,有兴趣的可以自己研究一下。

sizeof与数组

我们在上一章一维数组与二维数组的讲解里,就讲到了数组名是首元素地址,只有sizeof(数组名),这里的数组名才表示整个数组。那么大家看如下代码:

#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//(4)
}
int main()
{
int arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr));//(1)
printf("%d\n", sizeof(ch));//(3)
test1(arr);
test2(ch);
return 0; }

这里的(1)、(2)、(3)、(4)的值分别是多少呢?

我相信肯定很多人都回答不对,正确答案应该是40 4 10 4首先,1和3大家肯定都知道,因为sizeof数组名求的是整个数组大小,arr是整型数组,一个元素4个字节,10个元素就是40,ch为字符类型数组,一个元素占1个字节,一共10个,也就是10

那么问题就出在2和4了,我们要知道,这里的2和4里面的arr和ch其实是test()函数传过去的,test()函数传过去的是首元素地址,而一个地址在32位机器下储存起来需要32个比特位空间,也就是4个字节,它跟类型是没关系的,只要是地址,32机器下存储就需要4个字节,所以2和4的大小都是四个字节,这里最容易出错。!!!

逻辑操作符

在前面章节也讲过了&&与||

这里有一点需要注意:a && b && c假如a为假,那么整体就为假,后面的b 和 c 都不会进行运算,因为&&相当于并且假如a真,b假,整体就为假,那么c就不会参与运算而a || b || c, ||相当于或者,只要有一个为假,就整体为假假如a为真,b为假,整体就为假,c就不会参与运算

360笔试题

1、

#include <stdio.h>
int main()
{
int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0; }

2、

#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++||++b||d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}

1首先,第一个,a++ && ++b && d++这里a为0,在C语言里,0代表假,所以b和d都不会参与运算,而a++表示先使用a,a再增加,所以这里的a用完后还要加1,所以abcd为: 1 2 3 4 

操作符详解(完)_#include_13

2这里i = a++||++b||d++;a=0为假,进行b的运算,++b,此时b=3,为真,整体就为假,d就不运算,a用完后还要++所以a=1,b=3,c=3,d=4,

操作符详解(完)_#include_14

整型提升

有些表达式的操作数在求值的过程中可能需要转换为其他类型。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升​。

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算

具体什么意思呢?看如下代码:

#include <stdio.h>
int main()
{
char a = 1;
char b = 2;
char c = a + b;
printf("%d", c);

}

操作符详解(完)_整型_15

算数转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。():类型强制转换

long double   doublefloatunsigned long intlong int unsigned int int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

标签:return,int,++,详解,操作符,printf,main
From: https://blog.51cto.com/u_15954929/6057448

相关文章

  • STM32定时器TIM_OC1PreloadConfig、TIM_ARRPreloadConfig函数详解
    ———————————————————————————————————————————版权声明:本文为CSDN博主「qlexcel」的原创文章,遵循CC4.0BY-SA版权协议,转载请......
  • 线程私有变量ThreadLocal详解
    本文已收录至Github,推荐阅读......
  • 高效字符串匹配算法——BM 算法详解(C++)
    定义BM算法是由Boyer和Moore两人提出的一种高效的字符串匹配算法,被认为是一种亚线性算法(即平均的时间复杂度低于线性级别),其时间效率在一般情况下甚至比KMP还要快3......
  • 线程私有变量ThreadLocal详解
    本文已收录至Github,推荐阅读......
  • Kubelet配置详解
    kind:KubeletConfigurationapiVersion:kubelet.config.k8s.io/v1beta1address:172.18.105.1#监听地址,kubelet提供服务所用的ip地址port:10250......
  • 【shell基础】Linux Shell 的“>/dev/null 2>&1” 详解
     >/dev/null2>&1的含义:将标准输出和错误输出全部重定向到/dev/null中,也就是将产生的所有信息丢弃。详细分析下:符号>等价于1>(系统默认为1,省略了先);所以">......
  • robots.txt详解[通俗易懂]
    大家好,又见面了,我是你们的朋友全栈君。怎样查看robots文件?浏览器输入主域名/robots.txtrobots.txt的作用robots.txt文件规定了搜索引擎抓取工具可以访问网站上的哪些......
  • 详解Redisson分布式限流的实现原理
    摘要:本文将详细介绍下RRateLimiter的具体使用方式、实现原理还有一些注意事项。本文分享自华为云社区《详解Redisson分布式限流的实现原理》,作者:xindoo。我们目前在工作......
  • HTML5+CSS3(六)-全面详解(学习总结---从入门到深化)
    目录​​CSS简介​​​​ CSS概念​​​​为什么需要CSS​​​​CSS和HTML之间的关系​​​​ 语法​​​​学习效果反馈​​​​ CSS的引入方式​​​​ 内联样式(行内......
  • Explain详解与索引最佳实战
    Explain用途分析mysql中sql语句的执行计划Explain变种5.7之前用explain加上extended在分析结果中会多出一列filtered5.7之前用explain加上partitions在分析的结果中会......