C语言-第五章:操作符详解

操作符详解

分类

  • 算数操作符
  • 移位操作符
  • 位操作符
  • 赋值操作符
  • 单目操作符
  • 关系操作符
  • 逻辑操作符
  • 条件操作符
  • 逗号表达式
  • 下标引用,函数调用和结构成员

算数操作符

功能
/ 除
  • /除,求得的是商

  • 整数

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int a = 5 / 2;  //商2余1
        printf("a = %d\n", a);
        return 0;
    }
    
    //输出: 2
    
  • 小数

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        double a = 5 / 2.0;  
        printf("a = %lf\n", a);
        return 0;
    
    }
    
    //输出:a = 2.500000
    

    要想输出是小数,两端必须有一个是小数

% 取模
  • %取模,求得的是余数
注意事项
  • 除了%操作符外,其他的几个操作符可以作用于整数和浮点数
  • 两数都为整数就执行整数除法,只要有浮点数就是浮点数除法
  • %操作符的两个操作数必须为整数,返回的是整除之后的余数

移位操作符

右移
算数右移

右边丢弃,左边补原符号位

#include <stdio.h>
#include<string.h> 
int main()
{
    int a = 16;
    //>>  -- 右移操作符
    //移动的是二进制位
    int b = a >> 2;
    printf("%d\n", b);

    return 0;
}

//输出:4
#include <stdio.h>
#include<string.h> 
int main()
{
    int a = -1;
    //正数的二进制表示有:原码,反码,补码
    //存储到内存的是补码
    // 100000000000000000000000000000001  - 原码
    // 111111111111111111111111111111110  - 反码
    // 111111111111111111111111111111111  - 补码

    int b = a >> 2;
    printf("%d\n", b);

    return 0;
}

//输出:-1
逻辑右移

右边丢弃,左边补0

左移
  • 左边丢弃,右边补0
#include <stdio.h>
#include<string.h> 
int main()
{
    int a = 5;
    //正数的二进制表示有:原码,反码,补码
    //存储到内存的是补码
    // 100000000000000000000000000000001  - 原码
    // 111111111111111111111111111111110  - 反码
    // 111111111111111111111111111111111  - 补码

    int b = a << 1;
    printf("%d\n", b);

    return 0;
}

//输出:10
  • 左移相当于x2
注意
  • 对于移位操作符,不要移动负数位,这个是标准未定义的
num >> -1;  //error
  • 只能作用于整数

位操作符

类型
  • & 按位与
  • | 按位或
  • ^ 按位异或
按位与
#include <stdio.h>
#include<string.h> 
int main()
{
    //  - 按2进制位与
    int a = 3;          //011
    int b = 5;          //101
    int c = a & b;
    printf("%d\n", c);
    return 0;
}

//有一个0就是0,都是1才为1
//输出1
按位或
  • 与上相反,输出7
按位异或
  • 对应二进制位相同为0,相异为1
练习
  • 通过异或实现两个数值的交换

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        //  - 按2进制位与
        int a = 3;
        int b = 5;
       
        printf("before : a=%d b =%d\n",a,b);
    
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
    
        printf("after : a=%d b =%d\n", a, b);
        return 0;
    }
    
  • 求一个整数存储在内存中的二进制中的1的个数

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int num = 10;
        int count =0;
        scanf("%d", &num);
        //统计num的补码中有几个1
        while (num)
        {
            if (num % 2 == 1)
                count++;
            num = num / 2;
        }
        printf("%d\n", count);
        return 0;
    }
    
    //问题:算负数就出现问题
    

    针对上述负数出现问题,换一种算法

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int num = 0;
        int count = 0;
        scanf("%d", &num);  //-1
    
        int i = 0;
        for (i = 0; i < 32; i++)
        {
            if (1 == ((num >> i) & 1))
                count++;
        }
        printf("%d\n", count);
    }
    
    //输入:-1,输出:32
    //用到了按位与,移位操作符
    

赋值操作符

复合赋值符
a = a+2;
a += 2;

a = a >> 1;
a >> =1;

单目操作符

类型
  • !逻辑反操作,真变假,假变真

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int a = 0;
        if (!a)  //a为假打印呵呵
        {
            printf("呵呵\n");
        }
    }
    
  • - 负值

  • + 正值

  • & 取地址

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

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int a = 10;
        char c = 'r';
        char* p = &c;
        int arr[10] = { 0 };
        //sizeof计算的是变量所占内存空间的大小,包含数组,-单位是字节
        printf("%d\n", sizeof(a));  //4
        printf("%d\n", sizeof(c));  //1
        printf("%d\n", sizeof(p));  //4或8
        printf("%d\n", sizeof(arr));  //40
    
    }  
    
    //数组也是有类型的,去掉名字就是类型
    

小练习:判断输出的是几

#include <stdio.h>
#include<string.h> 
int main()
{
    short s = 0;
    int a = 10;
    printf("%d\n", sizeof(s = a + 5));
    printf("%d\n",s);
}

//输出:2,0
//sizeof里面的值是不参与运算的,所以s的值是0
  • ~ 对一个数的二进制按位取反

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int a = 0;
        //~按(2进制)位取反
        //00000000000000000000000000000000
        //11111111111111111111111111111111 按位取反后的结果,也是补码,我们打印的是原码
        //11111111111111111111111111111110 -反码
        //10000000000000000000000000000001 -原码
        //-1
        printf("%d\n", ~a);
    
        return 0;
    }
    
  • – 前置,后置–

    • 前置++,先++,再使用

      #include <stdio.h>
      #include<string.h> 
      int main()
      {
          int a = 10;
          printf("%d\n", ++a);
          return 0;
      
      }
      
      //输出:11
      
    • 后置++,先使用,再++

      #include <stdio.h>
      #include<string.h> 
      int main()
      {
          int a = 10;
          printf("%d\n", a++);
          printf("%d\n", a);
          return 0;
      
      }
      
      //输出:10,11
      
  • 间接访问操作符(解引用操作符)

    int main()
    {
        int a = 0;
        int* p = &a; //取地址操作符
        *p;  //解引用操作符,通过p里面存的值,找到它所指向的对象,*p就是它指向的对象a
    }
    
  • (类型) 强制类型转换

    #include <stdio.h>
    #include<string.h> 
    int main()
    {
        int a = (int)3.14;
        return 0;
    
    }
    

关系操作符

  • !=用于测试“不相等“
  • == 用于测试相等

逻辑操作符

  • &&逻辑与

    int main()
    {
        int a = 0;
        int b = 5;
        int c = a&&b;
        printf("%d\n",c);
        return 0;
    }
    
    //输出:1
    
  • ||逻辑或

    i = a++||++b||d++
    //只要第一个为真了,后面就不用算了
    
    这种行为是由 C 语言的语法规定和计算机底层实现机制决定的。当表达式的第一个操作数求值为真值时,计算机不需要再对后面的操作数进行求值,因为已经可以确定整个表达式的值了。这种行为可以减少计算机的计算量,提高程序的运行效率。
    

条件操作符

exp?exp2:exp3
练习
if (a>5)
    b=3;
else
    b=-3;

b = (a>5?3:-3);
return 0;

逗号表达式

定义

逗号表达式,就是用逗号隔开的多个表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果

"get_val" 函数的定义是一个计算机程序中的一段代码,用于获取一个特定的值或变量
get_val" 函数需要传递一个参数来告诉它需要获取什么值。然后,函数会在程序中找到并返回该值
形式
exp1,exp2,exp3,...expN

下标引用,函数调用,结构成员

[]下标引用操作符

操作数:一个数组名+一个索引值

int arr[10];  //创建数组
arr[9] = 10;  //使用下标引用操作符
[]两个操作数是arr和9,一个是数组名,一个是下标值
()函数调用操作符

函数调用操作符接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数是传递给函数的参数

结构成员
  • 访问一个结构的成员

    . 结构体.成员名
    -> 结构体指针->成员名
    
#include <stdio.h>
#include<string.h> 
//创建一个结构体类型 - struct Stu
struct Stu
{
    //成员变量
    char name[20];
    int age;
    char id[20];
};
int main()
{
    int a = 10;
    struct Stu s1 = { "张三",20,"2019010305" };
    printf("%s\n", s1.name);
    printf("%d\n", s1.age);
    printf("%s\n", s1.id);
    //结构体变量.成员名
    return 0;
}


//main函数里面也可以
int main()
{
    int a = 10;
    //使用struct Stu这个类型创建了一个学生对象s1
    struct Stu s1 = { "张三",20,"2019010305" };
    struct Stu* ps = &s1;

    printf("%s\n", ps->name);
    //结构体指针->成员名
    return 0;
}

整型提升

隐式类型转换

C的整型算数运算总是至少以缺省整型类型的精度来进行的

为获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

提升方法

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

例子
#include <stdio.h>
#include<string.h> 
int main()
{
    char a = 1;
    short b = 2;
    int c = 3;
    if (a == 1)
        printf("a");
    if (b == 2)
        printf("b");
    if (c == 3)
        printf("c");
    return 0;
}

//输出:只打印c的值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值