• C语言操作符(按位与 ,按位或,按位异或,整形提升)


    目录

    移位操作符

    位操作符

    赋值操作符

    单目操作符

    逻辑操作符

     条件操作符

    隐式类型转换(整形提升)


    移位操作符

    移位运算符是将数据看成二进制数,对其进行向左或向右移动若干位的运算。位移位运算符分为左移和右移两种,均为双目运算符。第一运算对象是移位对象,第二个运算对象是所移的二进制位数。

    << 左移操作符

    >> 右移操作符  

    注:移位操作符的操作数只能是整数。(移动的是二进制位补码的表示)

    左移操作符

    移位规则: 左边抛弃、右边补0

     向左移动一位实际上是将正整数数扩大一倍。(负数缩小一倍。)

    右移操作符

    移位规则: 首先右移运算分两种:

    1. 逻辑移位 左边用0填充,右边丢弃

    2. 算术移位 左边用原该值的符号位填充,右边丢弃(绝大多数编译器中采用的是算术右移)

    警告⚠ : 对于移位运算符,不要移动负数位,这个是标准未定义的。

    例如:

    1. int num = 10;
    2. num>>-1;//error

    位操作符

    &  //按位与

    |   //按位或

    ^  //按位异或

    注:他们的操作数必须是整数。(二进制)

    & (按位与):参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。

    | (按位或):参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。

    ^(按位异或):参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。

      

    例题: 

    不能创建临时变量(第三个变量),实现两个数的交换。 

    1. #include
    2. int main()
    3. {
    4. int a = 10;
    5. int b = 20;
    6. a = a^b;
    7. b = a^b;
    8. a = a^b;
    9. printf("a = %d b = %d\n", a, b);
    10. return 0;
    11. }

    一般我们在实际中不会用到这样的代码来交换两个变量,因为这样的代码可读性不高。 

    例题:

    编写代码实现:求一个整数存储在内存中的二进制中1的个数。 

    1. #include
    2. int main()
    3. {
    4. int num = -1;
    5. int i = 0;
    6. int count = 0;//计数
    7. while(num)
    8. {
    9. count++;
    10. num = num&(num-1);
    11. }
    12. printf("二进制中1的个数 = %d\n",count);
    13. return 0;
    14. }

    赋值操作符

    赋值操作符可以连续使用

    比如:

    1. int a = 10;
    2. int x = 0;
    3. int y = 20;
    4. a = x = y+1;//连续赋值

    赋值是从右往左。 

    复合赋值符

    +=

    -=

    *=

    /=

    %=

    >>=

    <<=

    &=

    |=

    ^= 

    1. int x = 10;
    2. x = x+10;
    3. x += 10;//复合赋值
    4. //其他运算符一样的道理。这样写更加简洁。

    那同样的语义:

    1. x = y+1;
    2. a = x;

    这样的写法更加清晰爽朗而且易于调试。 

    单目操作符

    单目操作符介绍

    !           逻辑反操作

    -           负值

    +           正值

    &           取地址

    sizeof      操作数的类型长度(以字节为单位)

    ~           对一个数的二进制按位取反

    --          前置、后置--

    ++          前置、后置++

    *           间接访问操作符(解引用操作符)

    (类型)       强制类型转换  如:(int*)

    sizeof求变量(类型)所占空间的大小。

    注意:

    sizeof是一个操作符,不是函数。sizeof内部放的表达式不计算。

    1. #include
    2. void test1(int arr[])
    3. {
    4. //指针大小是四个字节
    5. printf("%d\n", sizeof(arr));//4 int*arr
    6. }
    7. void test2(char ch[])
    8. {
    9. printf("%d\n", sizeof(ch));//4 char*ch
    10. }
    11. int main()
    12. {
    13. int arr[10] = {0};
    14. char ch[10] = {0};
    15. //这里数组名是整个数组的地址
    16. printf("%d\n", sizeof(arr));//40
    17. printf("%d\n", sizeof(ch));//10
    18. test1(arr);
    19. test2(ch);
    20. return 0;
    21. }

     数组名是数组首元素的地址,但是有两个例外:

    1.sizeof(数组名),数组名表示整个数组,不是首元素的地址。sizeof(数组名)计算的是整个数组的大小,单位是字节。

    2.&数组名,数组名表示整个数组,不是首元素的地址。&数组名取出的是整个数组的地址。

    求反运算符~  

    为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。

    例如~9的运算为: ~(0000000000001001)    结果为:1111111111110110 

    逻辑操作符

    &&      逻辑与

    ||         逻辑或

    区分逻辑与按位与

    区分逻辑或按位或

    1&2----->0

    1&&2---->1

    1|2----->3

    1||2---->1

    1. #include
    2. int main()
    3. {
    4. int i = 0,a=0,b=2,c =3,d=4;
    5. i = a++ && ++b && d++;
    6. //i = a++||++b||d++;
    7. printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);//a=1,b=2,c=3,d=4
    8. return 0;
    9. }

    a++先使用后++,a=0,逻辑与结果为假,a++后a=1

    逻辑与:当a++为假,后面的语句就不再执行了 。所以a=1,b=2,c=3,d=4。

     条件操作符

    也叫做三目运算符 

    if (a > 5)  

         b = 3;

    else  

         b = -3;

    转化为三目运算符

    a > 5 ? b = 3: b = -3;

    隐式类型转换(整形提升)

    C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

    整型提升的意义:

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

    1. //实例1
    2. char a,b,c;
    3. ...
    4. a = b + c;

    b和c的值被提升为普通整型,然后再执行加法运算。

    加法运算完成之后,结果将被截断,然后再存储于a中。 

     如何进行整体提升呢?

    整形提升是按照变量的数据类型的符号位来提升的

    负数的整形提升

    char c1 = -1; 变量c1的二进制位(补码)中只有8个比特位: 1111111 因为 char 为有符号的 char 所以整形提升的时候,高位补充符号位,即为1 提升之后的结果是: 11111111111111111111111111111111

    正数的整形提升

    char c2 = 1; 变量c2的二进制位(补码)中只有8个比特位: 00000001 因为 char 为有符号的 char 所以整形提升的时候,高位补充符号位,即为0 提升之后的结果是: 00000000000000000000000000000001 

    无符号整形提升,高位补0

    在计算的过程中发生了整形提升,所以sizeof会计算出四个字节。 

  • 相关阅读:
    [iOS开发]NSOperation & NSOperationQueue
    射频微波芯片设计3:射频微波芯片设计基础知识
    基于SpringBoot的“幼儿园管理系统”的设计与实现(源码+数据库+文档+PPT)
    PaddleSeg分割框架解读[01] readme解读
    Vue子组件修改父组件的值
    安装Linux虚拟机——以ubuntukylin-16.04.7-desktop-amd64.iso为例
    [附源码]java毕业设计农贸产品交易系统
    java python+vue运动场地租赁管理系统
    理解单点登录
    ⭐每天一道leetcode:21.合并两个有序链表(简单;双指针)
  • 原文地址:https://blog.csdn.net/m0_55752775/article/details/127455468