操作符详解(C语言)

目录

操作符分类

操作符详细讲解

1  算数操作符: +  -  *  /

2   移位操作符: >>   <<            

3   位操作符: & | ^

4   赋值操作符:=    +=    -= .....

5      单目操作符     (只有一个操作数) 

6   关系操作符

7   逻辑操作符

8   条件操作符

9   逗号表达式

10  下标引用、函数调用和结构成员


操作符分类

1、算数操作符   

+        -        *        /

2、移位操作符       

>>        <<         

3、位操作符           

&        |        ^             

4、赋值操作符        

+=       -=       *=       /=       %=       >>=       <<=       &=       |=        ^=        

5、单目操作符        !        -        +        &        sizeof        ~        --        ++        *        (类型)            

6、关系操作符       

>        >=        <        <=        ==        !=        

7、逻辑操作符     

&&        ||        

8、条件操作符       

表达式1 ? 表达式2 :表达式3        

9、逗号表达式        

exp1, exp2, exp3, ...expn;        

10、下标引用、函数调用和结构成员       

[ ]        ( )        .        ->        

操作符详细讲解

1  算数操作符: +  -  *  /

整型除法:1/2-->0
浮点数的除法:1.0/2-->0.5
%:取模操作符两边必须时整型。弄懂负数取模


2   移位操作符: >>   <<            

(只能对整数进行操作,不支持浮点数)

        移动的是二进制补码,因此在讲移位操作符之前,先了解一下补码是什么。

什么是补码?

        正反补码(计算机中正负数的表示)
        正的整数的原码、反码、补码相同
        负数的原码、反码、补码是需要计算的

        对于数字“7”来说,他的原码、反码和补码如下
        00000000000000000000000000000111 - 原码
        00000000000000000000000000000111 - 反码
        00000000000000000000000000000111 - 补码

        对于数字“-7”来说,他的原码、反码和补码如下
        10000000000000000000000000000111 - 原码
        11111111111111111111111111111000 - 反码(原码符号位不变,其他位按位取反就是反码)
        11111111111111111111111111111001 - 补码(反码+1就是补码)

        整数在内存中存的是补码

下面开始讲移位操作符:

左移操作符:<<

左边丢弃,右边补0
效果:乘2

#include <stdio.h>

int main()
{
    int a = 7;
    int b = a << 1;
    printf("%d\n", a);
    printf("%d\n", b);
    return 0;
}

右移操作符: >> 

算数移位:右边丢弃,左边补原符号位(正数补0,负数补1)。
逻辑移位:右边丢弃,左边补0。
对于正数来讲是一样的,但是对于负数来说,两种逻辑不同。
vs2019编译器采用的是算数右移(一般来讲编译器都采用的是算数右移)

移位操作不要移动负数位,这是标准未定义的。基本认为是错误的

3   位操作符: & | ^

   :  按(2进制)位与
     :  按(2进制)位或
 ^     :  按(2进制)位异或

int main()
{
    int a = 3;
    int b = -5;
    int c = a & b;
    //00000000000000000000000000000011 -  3的补码
    //11111111111111111111111111111011 -  (-5)的补码
    //00000000000000000000000000000011 -  3&(-5)的结果(补码也是原码)  
    //按位与:补码位都为1则为1,其他情况都是0,求出来的数是补码,转回原码就是输出值。
    int d = a | b;
    //11111111111111111111111111111011 -  3|(-5)的结果(补码)
    //10000000000000000000000000000101 -  3|(-5)的结果(原码码)
    //按位或:补码位只要其中一个为1则为1,都是0才为0,求出来的数是补码,转回原码就是输出值。
    int k = a ^ b;
    //11111111111111111111111111111000  -  3^(-5)的结果(补码)
    //10000000000000000000000000001000  -  3^(-5)的结果(原码) 
    //按位异或:相同则为0,相异为1,求出来的是补码,要把原码换回原码。
    printf("%d\n", c);
    printf("%d\n", d);
    printf("%d\n", k);
    return 0;
}

谈谈异或(^)的性质
        a^a=0
        0^a=a
        a^a^b=b
        a^b^a=b
        a^a^b=a^b^a  交换律

利用性质写了一个a、b交换的代码,中间不需要建立临时变量

int main()
{
    int a = 3;
    int b = -5;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;     //三次异或实现交换,不需要建立新的临时变量
    printf("%d %d", a, b);
    return 0;
}

练习:求一个证书存储在内存中二进制的个数

int main()
{
    int a = 5;   //00000000000000000000000000000101   结果应为2
    int i = 0;
    int count = 0; //用于计数
    for (i = 0;i < 32;i++)
    {
        if (a & 1 == 1)    //1的二进制为00000000000000000000000000000001
        {
            count++;
        }
        a = a >> 1;   //a右移一位判断下一位
    }
    printf("%d", count);
    return 0;
}

4   赋值操作符:=    +=    -= .....

        赋值操作符是一个很棒的操作符,它可以让你得到你之前不满意的值,也就是可以重新赋值。(初始化是初始化,赋值是赋值,二者之间是有区别的)
 int a = 0; 这叫初始化。
 a = 100; 将100赋值给a。这是赋值
 a = x = y+1; 连续赋值也是可以的,但是不建议。可读性不好。

复合赋值符:+=  -=  *=  /=  %=  >>=  <<=  &=  |=  ^=
        这些是将赋值和前面的其他操作符符合
如:a += 5  ;  和   a = a + 5 ;  这两个一模一样
    a >>= 5  ; 和   a = a >> 5 ; 这两个一模一样
    a &= 5  ;  和   a = a & 5 ;  这两个一模一样
不难发现这些符合都是用同样的规则将表达式简化而已。

5      单目操作符     (只有一个操作数) 

单目操作符包括:

!       逻辑反操作                  
 -       负值
 +       正值
 &       取地址

 sizeof  操作数类型的长度(以字节为单位)
 ~       对一个二进制数进行取反    
--       前置、后置--
++       前置、后置++ 
*        间接访问操作符(解引用操作符)
(类型)   强制类型转换

下面进行详细讲解:

 !       逻辑反操作  

int main()
{
    int flag = 3;
    if (flag)   //flag为真进入此if语句
    {
    }
    if (!flag)  //flag为假进入此if语句
    {
    }
}
c语言中,非0表示真,0表示假。


 -       负值
 +       正值
int main()
{
    int a = 10;
    int b = +a;              //正值a
    int c = -a;              //负值a
    printf("%d %d", b, c);   //输出10 -10
}


 &       取地址

int main()
{
    int a = 0;
    printf("%0Xd\n", &a);  //将a的首地址输出
    int* p = a;            //地址需要用指针存放
    return 0;
}

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

int main()
{
    int a = 0;
    int b[5] = { 0 };
    int n = sizeof(a);//sizeof是一个操作符,计算a所占内存的大小,单位是字节
    int k = sizeof(int);//sizeof也可以计算类型的大小(其实是类型创建的变量所占内存空间的大小,因为类型本身没有大小)。单位都是字节
    int l = sizeof(b);//sizeof还可以计算数组的大小。单位是字节。
    printf("n=%d k=%d l=%d\n",n,k,l);//n=4 k=4 l=20
    return 0;
}

当sizeof用于测量变量大小时,后面的括号可以去掉,这点说明了sizeof并不是一个函数。
但是要对类型进行测量时,如:sizeof(int)。此时就不能去括号。

 ~       对一个二进制数进行取反    

int main()
{
    int a = 0;
    printf("%d\n", ~a);   //对a的二进制序列(补码)按位取反再输出,这里输出为-1
    return 0;
}


--       前置、后置--

int main()
{
    int a = 1;
    printf("%d\n", a--);//先进行打印,后a=a-1。这里输出为1。
    a = 1;
    printf("%d", --a);//先进行a=a-1,后打印.这里输出为0。
    return 0;
}


++       前置、后置++ 

main()
{
    int a = 1;
    printf("%d\n", a++);//先进行打印,后a=a+1。这里输出为1。
    a = 1;
    printf("%d", ++a);//先进行a=a+1,后打印。这里输出为2。
    return 0;
}


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

int main()
{
    int a = 10;
    int* p = &a;     //用&取出a的地址赋值给p(上面讲了&作用)
    printf("%d", *p);//这里是将a的地址放在了p中,然后通过*对p进行访问,将p地址对应的内存输出,即将a输出。输出结果为10。
    return 0;
}


(类型)   强制类型转换

int main()
{
    int a = 1;
    printf("%f", (float)a);//将本来int类型的a强制转化为float类型输出,输出结果为1.000000。之后的a都变成了float类型,不会变回int类型了。
    printf("%d", a);//输出结果1.0000001
    return 0;
}

另一个例子: 

int main()
{
    int a = (int)3.14;
    printf("%d\n", a);//将3.14这个小数(默认是double类型),强制转化成整型,输出。这里输出为3。
    int b = (int)3.6;
    printf("%d\n", b);//这里输出b的值为3,说明强制取整就是将整数部分取出,并不会进行四舍五入。
    return 0;
}


6   关系操作符

 >       大于
 >=      大于等于
 <       小于
 <=      小于等于
 !=      用于测试“不相等”
 ==      用于测试“相等”

注意:“==”和“=”的区别。前者是判断相等,后者是赋值。
        在运用“==”是,注意,不能用于比较数组相不相等,如果这样写:"abc"=="abcdef"。这样不是在比较两个字符串数组的内容是否相等,而是在比较两个字符串首地址相不相等。

7   逻辑操作符

逻辑操作符有两种:
&&   逻辑与
||   逻辑或


逻辑与(&&)和按位与(&)区别

 1&&3 结果为 1
 1&0  结果为 0

逻辑或(||)和按位或(|)区别

 1||2 结果为1
 1|2  结果为3

注意:
&& 左边为假,右边就不计算了
|| 左边为真,右边就不计算了
例如:

int a = 1;
int i = 0&&(a = a+3);

这样算完a的值还是1,a = a + 3这个算式不计算,因为&&左边为0,即左边为假。i的值最后为0

同理:

int b = 2;
int i = 1||(b = b-2);

这样算完b的值还是2,不计算 b = b + 2。i的值最后为1。


8   条件操作符

表达式1 ? 表达式2 :表达式3
      真              √               ×
      假              ×               √  

如:

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

        这样的表达式,最后b的值就为 -3 。因为 a = 3 不满足a > 5这个式子,所以整个条件表达式  a > 5 ? 3 : -3 的值就为 : 后面的结果,即为-3。即相当于b = -3。
可以在表达式1 、 表达式2 、 表达式3 中进行运算,但不建议写得太复杂,这样不便于程序理解,可读性会降低。

9   逗号表达式

        用逗号隔开的多个表达式即为逗号表达式
        形式: exp1, exp2, exp3, ...expn;
        逗号表达式运行情况:从左向右以此执行。整个表达式的结果是最后一个表达式的结果。
如:

int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//这里c的值最后为13,即b=a+1的结果。

        注意,虽然逗号表达式结果为最后一个表达式的结果,但是中间的表达式不可忽略,因为中间的表达式会改变最后表达式中的参数的值。
比如上面这个例子,a在第二个表达式中被赋值为b+10也就是12,因此在最后b=a+1的值才为13。

10  下标引用、函数调用和结构成员

1  [ ]  :下标引用操作符

如:

int arr[10] = { 0 };
arr[7] = 8;   //arr和7是[]的操作数,他们可以调换位置,可以写成 7[arr] 是一样的,但是这样写挺怪的,不推荐。

2  ( )  :函数调用操作符

如:

int Add(int a, int b)
{
    return a + b;
}
int main()
{
    int a = 10;
    int b = 20;
    int c = Add(a, b); //这里调用Add函数用的()就是函数调用操作符。因为sizeof可以省略()去计算变量大小,所以sizeof并不是函数。
    printf("%d", c);   //这里输出为30
    return 0;
}

3 结构访问操作符

1    .           结构体.成员名
2    ->        结构体指针->成员名
 如:

struct Stu
{
    char name[20];
    int age;
    double score;
};

void set_stu(struct Stu* ss)
{
    strcpy((*ss).name, "zhengsan");  //这里用了strcpy函数,要在程序开头调用库函数:#include <string.h>。
    (*ss).age = 20;
    (*ss).score = 100.0;

    strcpy(ss->name, "zhengsan");   //这里和上面达到的效果是一样的。因此我们发现 ss->age 完全相当于 (*ss).age。
    ss->age = 20;
    ss->score = 100.0;
}

void print_stu(struct Stu ss)
{
    printf("%s %d %lf", ss.name, ss.age, ss.score);
}

int main()
{
    struct Stu s = { 0 };
    set_stu(&s);
    print_stu(s);
    return 0;
}

        以上就是所有操作符的讲解了。如果对你了解操作符有帮助的话,我会很开心。


 

  • 33
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彭逍遥

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值