【C语言跬步积累】——操作符

189 阅读9分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

介绍:

算数操作符:+(加号) -(减号) *(乘号) /(除号) %(取模)

移位操作符:>> (右移) <<(左移)

位操作符:&(按位与) |(按位或) ^(按位异或)

赋值操作符:= += -= *= /= $= ^= |= >>= <<=

单目操作符:!(逻辑反操作) -(负值) +(正值) &(取地址) sizeof(操作数的类型长度,以字节为单位) ~(对一个数的二进制按位取反) ++ -- *(间接访问操作符/解引用操作符) (类型)(强调类型转换)

关系操作符:>(大于) >=(大于等于) <(小于) <=(小于等于) !=(不等于) ==(等于)

逻辑操作符:&&(逻辑与) ||(逻辑或)

条件操作符:exp1 ? exp2 : exp3(也叫三目操作符)

逗号表达式:exp1, exp2, exp3, ... ,expN(用逗号隔开的表达式就是逗号表达式) 下标引用,函数调用操作符:[ ] ( )

一.算数操作符

加减乘除我就不过多介绍,算数操作符我就简单介绍一下除号(/)和取模(%)之间的区别

区别:/是用来取商而%是用来取余数

例析:

#include<stdio.h>
int main()
{
int a=5/2;
printf("%d\n",a);
return 0;
}
#include<stdio.h>
int main()
{
int a=5%2;
printf("%d\n",a);
return 0;
}

总所周知:5➗2=2……1

因此第一个代码输出的结果应该是2(商),第二个代码输出的结果应该是1(余数)

二.移(二进制)位操作符: 

1.先简单介绍一下十进制和二进制之间的转换规律(用电脑打字解释起来有点费劲,就直接手写了,如果还不能理解可以私信问我)

image.png (我也不知道为什么会是这样,就将就着看一下吧)

2.例析(以在<<为例,>>同理)

#include<stdio.h>
int main()
{
int a=1;//整型1占4个字节——32个bit位
        //因此1用二进制表示应是:00000000000000000000000000000001(不用数了,一共32位)
int b=a<<1;//a向左移了一位之后: 00000000000000000000000000000010(十进制表示为2)
printf("%d\n",b);
return 0;
}

输出结果:2

思考:如果在上面代码的基础上再顺手打印一下a,那么a的值是几呢?

答案是:1

相当于你移位之后原来a的值是不变的(除非移位之后再将值赋给a),你打印的b是a移位之后的值,a还是原来的a

三.(二进制)位操作符 

补充:规定0为假,非0为真 

1.&(按位与)

#include<stdio.h>
int main()
{
int a=3;//3转化为二进制是011
int b=5;//5转化为二进制是101
int c=a&b;//a:⬇011(0为假,非0为真),从上往下对应着看
          //b:⬇101
          //c: ⬇0(0和1按位与为0)0(1和0按位与为0)1(1和1按位与为1),所以c的二进制数为001,打印的结果是1
printf("%d\n",c);
return 0;
}

输出结果:1

总结:

&:0和1为0,1和1为1,0和0为0

2.|(按位或)

#include<stdio.h>
int main()
{
int a=3;    //011
int b=5;   //101
int c=a|b;  //111        
printf("%d\n",c);
return 0;
}

输出结果:7

总结:

1和1为1,1和0为1,0和0为0(只要与一个1结果就是1)
举个例子:你早上要吃早饭,现在有a套餐和b套餐,你只要选则其中一种,吃早饭这一项任务就完成了(当然a,b套餐都吃也可以)

3.^(按位异或)

(不是次方的意思)

    #include<stdio.h>
  int main()
  {
  int a=3; //011
  int b=5; //101
  int c=a^b; //110
  printf("%d\n",c);
  return 0;
  }

输出结果:6

总结:

对应二进制位相同,则为0;对应二进制位相异,则为1

四.赋值操作符

a=20;(=是赋值,==是判断相等)

a=a+10;可以写成:a+=10;

a=a-10;可以写成:a-=10;

a=a&2;可以写成:a&=2;

……(其他同理)

五.单目操作符

(也有双目操作符,三目操作符,区别在于操作数的不同,单目操作符有一个操作数,双目操作符有两个操作数,三目操作符有三个操作数)

1.!(逻辑反操作)

(c语言中0表示假,非0为真)

#include<stdio.h>
int main()
{
int a=10;
printf("%d\n",a);
printf("%d\n",!a);
return 0;
}

输出结果:10

                   0

解释:

10为非0,因此为真,而!a则会将真变为假,及将10变为0

思考:

如果a=0,那么!a=?

结果:1

解释:

0为假,!a则将假变为真,在假变为真时,只会变为1

2.+和-

用来表示正数和负数

3.sizeof(计算变量或者类型所占空间的大小,单位是字节)

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

输出结果:4

                   4

     注意:sizeof计算变量时可以省略括号,但计算类型时不能省

计算数组大小:

#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%d\n",sizeof(arr));
return 0;
}

输出结果:40

计算数组的元素个数(个数=数组总大小/每个元素的大小)

#include<stdio.h>
int main()
{
int arr[10]={0};
int sz=0;
printf("%d\n",sizeof(arr));
sz=sizeof(arr)/sizeof(arr[0]);
printf("sz=%d\n",sz);
return 0;
}

输出结果:40

                  sz=10

4.~(二进制按位取反)

补充:

  • 源码,反码,补码

  • 只要是整数(分正整数和负整数),内存中存储的都是二进制的补码

  • 正数的源码,反码,补码相同

  • 有符号的整型的最高位表示符号位(红色数字),如果为1表示负数,为0表示正数

  • 例(a和b与下面代码中的a和b相同): a=00000000000000000000000000000000(最高位为0,表示正数) b(有符号的整型)=11111111111111111111111111111111(最高位为1,表示负数,为补码,而打印的是这个数的源码)

  • 源码符号位不变,其他位按位取反得到反码,反码加一得到补码

  • 例1:补码:11111111111111111111111111111111 反码:11111111111111111111111111111110 源码:1000000000000000000000000001(1表示负数,因此得到-1)

  • 例2:-2 (十进制) 源码:10000000000000000000000000000010 反码:11111111111111111111111111111101 补码:11111111111111111111111111111110

#include<stdio.h>
  int main()
  {
    int a=0;//4个字节,32个bit位
  int b=~a;
  printf("%d\n",b);
  return 0;
  }

输出结果:-1

5.++和--

#include<stdio.h>
int main()
{
int a=10;
int b=a++;
printf("a=%d b=%d\n",a,b)
return 0;
}

输出结果:a=11 b=10

#include<stdio.h>
int main()
{
int a=10;
int b=++a;
printf("a=%d b=%d\n",a,b)
return 0;
}

输出结果:a=11 b=11

解释:

后置++:先将a的值赋给b,因此b为10,再将a++,所以a为11,即先使用,后++

前置++:先将a++,a的值变为11,再将a的值赋给b,因此b的值也为11

--同理

6.(类型)

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

如果没有(int)会有警告,因为int是定义整数变量,而3.14是小数,应该使用double类型,但如果你就想这样使用,可以加(int)进行强制类型转换(将double类型转换成int类型),这样就不会报错了

7.&(取地址操作符) 和*(解引用操作符)

#include<stdio.h>
int main()
{
int a=10;
printf("%p\n",&a);//可以打印出a所在的地址,%p用来打印地址,打印出来的是十六进制的,结果是随机的
return 0;,
}
#include<stdio.h>
int main()
{
int a=10;
int* p=&a;//int*是指针变量的类型,p为指针变量,该代码的目的是将a的地址存放在p中
printf("%p\n",&a);
printf("%p\n",p);//输出的两个结果是一样的
*p=20;//*是解引用操作符,*p是指对p进行解引用操作,找到它所指向的对象a,*p=20是指将通过*p找到的a的值改为20
printf("a=%d\n",a);//打印出的a的值应为20
return 0;,
}

image.png

解释:

int a=10;定义了一个变量a并赋值10,a的地址为0x0012ff40

int* p=&a;将a的地址放到p当中

*p=20;将a中的10改为20

这个是计组里的间接寻址方式,在这里不理解也没事,先了解一下,之后还会详细讲解的

六.关系操作符(略)

七.逻辑操作符 (与位操作符相似)

1.&&(逻辑与)

(再三强调:在C语言中,0为假,非0为真)

#include<stdio.h>
int main()
{
int a=3;//3为真
int b=5;//5为真
int c=a&&b;//真&&真为真,并且定义真为1
printf("c=%d\n",c);
return 0;
}

输出结果:c=1

总结:

&&:真&&真为真,真&&假为假,假&&真为假,假&&假为假 定义如果为真则结果为1,如果为假则结果为0

2.||(逻辑或)

#include<stdio.h>
int main()
{
int a=0;//0为假
int b=5;//5为真
int c=a||b;//假||真为真,并且定义真为1
printf("c=%d\n",c);
return 0;
}

输出结果:c=1

总结:

在||中,只要有一个为真结果就为真

八.条件操作符

exp1 ? exp2 : exp3(exp1,exp2,exp3是表达式的意思)(三目操作符)

#include<stdio.h>
int main()
{
int a=10;
int b=20;
int max=0;
max = (a > b ? a : b);
printf("max=%d\n",max);
return 0;
}

输出结果:max=20

解释:

max=(a>b?a:b);表示如果a>b成立,则将a的值赋给max,如果不成立,则将b的值赋给max 即如果?前的exp1成立,则输出exp2,如果exp1不成立,则输出exp3

补充另一段代码,和条件操作符相似:

#include<stdio.h>
int main()
{
int a=10;
int b=20;
int max=0;
if (a>b)
max=a;
else
max=b;
printf("%d\n",max);
return 0;
}

输出结果:20

解释:

这段代码使用if,else语句,也可以起到和条件操作符相同的作用,但相比之下,条件操作符较为简单

九.逗号表达式

解释:用,隔开的表达式即为逗号表达式

十.下标引用,函数调用和成员结构操作符

1.[ ](下标引用操作符)

#include<stdio.h>
int main()
{
int arr[10]={0};
arr[4];//[ ]为下标引用操作符,在上一篇文章讲解整型数组中有讲过,[4]为访问下标为4的元素
return 0;
}

2.( )(函数调用操作符)

#include<stdio.h>
int add(int x,int y)
{
int z=0;
z=x+y;
return z;
}
int main()
{
int a=10;
int b=20;
int sum=add(a,b);//( )调用前面定义的函数,因此叫函数调用操作符
return 0;
}

最后:

因为第一次写长篇文章,难免会犯些错误,希望能够指正,另外有什么好的建议以及问题可以在评论区提出