C语言之操作符

本文详细介绍了C语言中的操作符,包括单目操作符、移位操作符、位操作符、赋值操作符、单目操作符、逻辑操作符、条件操作符等,并通过案例展示了如何使用操作符交换两个整数的值以及计算二进制中1的个数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本节内容主要讲述的是c语言中一些操作符的作用以及使用案例


一、操作符是什么? 

指令系统的每一条指令都有一个操作符,它表示该指令应进行什么性质的操作。不同的指令操作符这个字段的不同编码来表示,每一种编码代表一种指令。

操作符详解:
(1)单目操作符:只有一个操作数的操作符
除法:/

得到小数:除数与被除数中至少一个是小数得到整数:除数与被除数必须都是整数
(2)移位操作符:

左移:<<

把a的二进制位向左移动一位: 左边移出去的丢弃,右边补0
int a = 2;  00000000 00000000 00000000 00000010

                00000000 00000000 00000000 00000100
int b = a << 1;  得到b = 4
右移 <<

把a的二进制位向右移动一位
右移分为两种算术右移:右边丢弃,左边补原符号位 正数补0 负数补1
                          逻辑右移:右移丢弃,左边补0 都补0
int a = 10;

00000000 00000000 0000000 00001010

00000000 00000000 0000000 00000101 - 5

int b = a >> 1; 得到b = 5

整数的二进制表示形式:
    原码:直接根据数值写出的二进制序列就是原码
    反码:原码的符号位不变,其他位按位取反就是反码
    补码:反码+1就是补码

注意:反码(补码-1)= 原码
 -1
    原码:10000000 00000000 00000000 00000001
    反码:11111111 11111111 11111111 11111110(除了符号位其他位全部取反
    补码:11111111 11111111 11111111 11111111(在内存中存储的形式就是补码

    补1不变 补0变正数
    真实的值:由补码推到原码就是
    int a = -1;
    int b = a >> 1; 得到a = -1
    不要移动负数位代码

(3)位操作符:操作数必须都是整数
    按位与: & (按二进制位进行与运算) 同0得0 同1得1 1和0得0 串
    int a = 3;  00000000 00000000 00000000 00000011
    int b = 5;  00000000 00000000 00000000 00000101
    int c = a & b; 00000000 00000000 00000000 00000001 
    //得到c = 1

    按位或: | 有1得1 否则为0 并
    int a = 3;  00000000 00000000 00000000 00000011
    int b = 5;  00000000 00000000 00000000 00000101
    int c = a & b; 00000000 00000000 00000000 00000111
    //得到c = 7

    按位异或:^ 对应的二进制位进行异或 规则:相同为0 相异为1
    int a = 3;  00000000 00000000 00000000 00000011
    int b = 5;  00000000 00000000 00000000 00000101
    int c = a & b; 00000000 00000000 00000000 00000110
    //得到c = 6

(4)赋值操作符:
    =  +=  -= /= >>= <<= %= &= |= ^=
(5)单目操作符:

    !(逻辑反操作:if(flag)   if(!flag)就是取反的作用) - + & sizeof ~ ++ -- * (类型)
    sizeof() 括号中的表达式不参与运算 表达式的类型是看左值的类型
    ~ 对一个数的二进制按位取反 
    -1:
    原码10000000 00000000 00000000 00000001 
    反码11111111 11111111 11111111 11111110
    补码11111111 11111111 11111111 11111111 反码+1 在内存中存储的是补码
    ~(-1)按位取反是 0
    int a = 13
    把a的二进制中的第五位置为1
    a = a | (1 << 4)
    把a的二进制中的第五位置为0
    a = a & ~(1 << 4)
    ++ --:
    int a = 10;
    b = a++; 后增先使用再加加 a = 11 b = 10
    b = ++a; 先增先加加后使用 a = 11 b = 11

   判断先增后增的方法:加号在前面是先增,加号在后面是后增
    *:
    间接访问操作符(解引用操作符)
    &:
    取地址操作符 打印地址的方式 %p
    int a = 10; 
    int * pa = &a; pa是用来存放地址的 pa就是一个指针变量也叫指针 这颗*告诉我们pa这是指针变量
    *pa 里的*就叫做解引用操作符 或者 间接访问操作符
():
    强制类型转换 int(c)
==:
    相等 比较两个字符串不能使用等号
(6)逻辑操作符:
    && 逻辑与 || 逻辑或 != 逻辑非 
    1个是按位  与 2个是逻辑与
(7)条件操作符:也称为三元操作符
    exp1 ? exp2 : exp3
    if(a > 5) b = 1; else b = -1;
    b = (a > 5) ? 1 : -1     max = (a>b? a:b)
   逗号表达式:由逗号隔开的一串表达式
   要从左向右计算 
    int d = (c = 5, a = c + 3, b = a - 4, c = c + 5); d = 10
    整个表达式的结果只取决于最后一个表达的结果
    例子:

    a = getval();
    count_val(a);
    while(a>0)
    {
        a = get_val();
        count_val(a);
        ...
    }


改用逗号表达式后:
    while(a = get_val(), count_val(a), a > 0) 1 2 判断作用的只有3
    while
    {
        ...
    }
[]下标引用操作符:
    int arr[10] = {1,2,3,4,5,6,7,8,9,10}
    arr[5] 这个[]就是下标引用操作符 操作数是arr, 4
()函数调用操作符:
    int a = 10;
    int b = 20;
    int ret = add(a, b); 这个()就是函数调用操作符
. ->结构成员访问操作符:
    int float char double short
    书:书名,书号,出版社,定价,作者
    人:姓名,性别,年龄
    struct book 定义结构体类型
    {
        char name[20];
        char id[20];
        int price;
    }; 封号不能少
    
    用类型创建了一本书
  

    struct book b = {"c语言","c20220226", "66"};
    printf("书名:%s\n书号:%s\n价格:%d\n", b.name, b.id, b.price);

    struct book * pb = &b;
    printf("书名:%s\n书号:%s\n价格:%d\n", b->name, b->id, b->price);
    printf("书名:%s\n书号:%s\n价格:%d\n", (*pb).name, (*pb).id, (*pb).price);
     //*pb就是对pb解引用,刚好就是b


表达式求值:
    表达式求值的顺序一部分是由操作符的优先级和结合性决定
    隐式类型转换:整型提升是按照变量的数据类型的符号位来提升
    内存中存储的是补码,而数值的大小是以原码来看 反码+1=原码
    整型提升(p74-操作符详解 是难点)
    值属性 类型属性
    只要参与表达式运算就会发生整型提升
    %u unsigned 打印无符号整数 sizeof返回的是一个无符号整数
    %d 打印有符号整数
算术转换:
    如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行
    int a = 4;
    float f = 4.5f;
    a + f; 需要int向float转换
操作符的属性:
    操作符的优先级 操作符的结合性 是否控制结合顺序
    static int count = 1;static的作用:隐藏 保持内容的持久  默认初始化为0
    总结:我们写出的表达式不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。
sizeof:操作符计算变量类型所占内存大小,单位是字节 包括\0
strlen:函数,求字符串长度,找\0之前出现的字符个数 

二、使用案例

1.交换两个int变量的值不能使用第三个变量

代码如下(示例):

#include <stdio.h>
int main(void)
{
    /*
    a = a + b;
    b = a - b;
    a = a - b; 遇到超过int能表示的最大值会溢出 -32678——32678
    */
    int a = 3; //00000000 00000000 00000000 00000011
    int b = 5; //00000000 00000000 00000000 00000101
    printf("交换前:a = %d b = %d\n", a, b);
    a = a ^ b;   //00000000 00000000 00000000 000000110
    b = a ^ b; //00000000 00000000 00000000 000000011 == 3
    a = a ^ b; //00000000 00000000 00000000 000000101 == 5
    printf("交换后:a = %d b = %d\n", a, b);  
        //异或没有产生进位,不会溢出 相同得0 不同得1
    // a^b^b = a 
    return 0;
}

2.输出整数的二进制数中1的个数,其中负数用它的补码表示

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int number1(unsigned int n)
{
    int count = 0;
    while (n)
    {
        if (n % 2 == 1);
        {
        count++;
        }
        n /= 2;
    }
    return count;
}
int main(void)
{
    /*
    计算参数n的二进制补码中有几个1:
    123得到10进制的每一位模10除10
    123%10=3
    123/10=12
    12%10=2
    12/10=1
    1%10=1
    1/10=0
    15---00001111
    15%2=1
    15/2=7---00000111
    7%2=1---00000001
    7/2=3---00000011
    3%2=1---00000001
    1%2=1---00000001
    1/2=0---00000000
    */
    int n = -1;
    int val = number1(n);
    printf("val = %d\n", val);
    return 0;
}


总结

整数的二进制表示形式:
    原码:直接根据数值写出的二进制序列就是原码
    反码:原码的符号位不变,其他位按位取反就是反码
    补码:反码+1就是补码
    -1
    原码:10000000 00000000 00000000 00000001
    反码:11111111 11111111 11111111 11111110
    补码:11111111 11111111 11111111 11111111(在内存中存储的形式就是补码)
    对于正整数来说原码 补码 反码相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dzq0311

谢谢支持,您的鼓励是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值