操作符详解(保姆级教程)

目录

一、操作符的分类

二、算术操作符

2.1 / 操作符

2.2 % 操作符

三、移位操作符

3.1 左移操作符

3.1.1 正整数的左移

3.1.2 负整数的左移

3.2 右移操作符

四、位操作符

4.1 & 按位与

4.2 | 按位或

4.3 按位异或

 4.4 一道相关面试题

五、赋值操作符

5.1 复合赋值符

六、单目操作符

6.1 单目操作符介绍

6.2 sizeof操作符

6.3 & 与 * 操作符

 七、关系操作符

八、逻辑操作符

 九、条件操作符

十、逗号表达式

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

11.1 [ ]下标引用操作符

11.2 ()函数调用操作符

11.3 访问一个结构体成员

一、操作符的分类

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

       在下文中我们会依次讲解这些操作符。

二、算术操作符

+          -          *           /           %

     在这里我们主要讲解/与%操作符。

2.1 / 操作符

对于 / 操作符,我们主要注意以下 :

  1. 对于/操作符,如果两个操作数都为整数,执行整数除法。如5/2=2;
  2. 如果两个操作数中有浮点数,执行的就是浮点数的除法。如5.0/2=2.5;

2.2 % 操作符

    %操作符的两个操作数都必须是整数,他求的是整除之后的余数。

三、移位操作符

<<  左移操作符

>>  右移操作符

     移位操作符移的是二进制的位。

     在计算机中,整型的二进制表示包括三种:原码、反码、补码。      

     我们分别使用15与-15来举例讲解其原码、补码以及反码。

15: 

-15:

注意:

  1. 在计算机内存中存储的是数据的补码。
  2. 在打印数据时,打印的是数据的原码结果。 

3.1 左移操作符

左移操作符的移位规则是:

 左边抛弃,右边补0:

3.1.1 正整数的左移

#include <stdio.h>
int main()
{
	int a = 4;
	int b = a << 1;
	printf("a = %d b = %d\n", a, b);

	return 0;
}

  接下来我们分析a<<1的结果:
  

     在上面的分析中,我们得知,进行移位操作后,b = 8, 那么a的值是否会发生变化呢?答案是不会。

      注意,a<<1时,a的值不会发生变化。

3.1.2 负整数的左移

      对于负数,在左移时相对复杂,我们举例来观察:

#include <stdio.h>
int main()
{
	int a = -4;
	int b = a << 1;
	printf("a = %d b = %d\n", a, b);

	return 0;
}

我们发现:

  1. 左移一位有*2的效果,即b = a<<1;相当于b = a*2;
  2. b = a<<1;左移不会改变a的值。 

3.2 右移操作符

右移操作符的移位规则:

 首先右移运算分为两种:

  1. 逻辑移位      左边用0填充,右边丢弃。
  2. 算术移位      左边用原该值的符号位填充,右边丢弃。

至于两种右移方式选择哪一种主要是看编译器,在大多数的编译器中采用算术移位。

我们来举例说明:

#include <stdio.h>
int main()
{
	int a = -4;
	int b = a >> 1;
	printf("a = %d b = %d\n", a, b);

	return 0;
}

上述代码结果为:

注意:对于移位操作符,不要移动负数位,这个是标准未定义的。

四、位操作符

位操作符有:

&          按位与(对应的二进制位按位与,如果有0则为0,两个同时为1才为1)

|            按位或(对应的二进制位按位与,如果有1则为1,两个同时为0才为0)

^           按位异或(对应的二进制位按位异或,如果相同为0,不同为1

注意,以上三个操作符的操作数都必须为整数。

上述的三种运算符都是对补码进行操作。

我们来通过具体的示例来讲解:

4.1 & 按位与

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	printf("c = %d\n", c);

	return 0;
}


 

      这里再次重申在内存中计算的时候是对补码进行运算,但是打印的时候,打印的是原码对应的十进制值。 

4.2 | 按位或

#include <stdio.h>
int main()
{
	int a = 3;
	int b = -5;
	int c = a | b;
	printf("c = %d\n", c);

	return 0;
}

4.3 按位异或

#include <stdio.h>
int main()
{
	int a = 3;
	int b = -5;
	int c = a ^ b;
	printf("c = %d\n", c);

	return 0;
}

 4.4 一道相关面试题

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

方法一:

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

     上述的方法存在一定的缺陷,如果a,b中存放的值都特别大,但是没有超出int类型的范围,那么a+b的值就会超过int类型的范围,会有一些数据在计算中丢失。

改进后的代码:

首先我们需要知道按位异或的几个特点:

  • 任何的数字与0异或,得到的结果依然是他自己。
  • 0与a异或,结果为a。
  • a与a异或,结果为0。
  • 异或支持交换律。
#include <stdio.h>
//3^3=0
//5^5=0
//3^5=6
//3^5^5=3
//3^5^3=5
int main()
{
    int a = 10;
    int b = 20;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("a = %d b = %d\n", a, b);
    return 0;
}

五、赋值操作符

例如:

int weight = 120;

5.1 复合赋值符

+=               a+=5;相当于a=a+5;

-=                a-=5;相当于a=a-5;

*=                a*=5;相当于a=a*5;

/=                a/=5;相当于a=a/5;

%=              a%=5;相当于a=a%5;

>>=             a>>=5;相当于a=a>>5;

<<=             a<<=5;相当于a=a<<5;

&=               a&=5;相当于a=a&5;

|=                a|=5;相当于a=a|5;

^=               a^=5;相当于a=a^5;

六、单目操作符

6.1 单目操作符介绍

!                               逻辑反操作

-                                  负值

+                                 正值

&                                 取地址

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

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

--                                  前置--,后置--

++                                前置++,后置++

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

(类型)                           强制类型转换

6.2 sizeof操作符

   注意:sizeof()内部存放的表达式是不会计算的。

例如:
 

int main()
{
	short s = 10;
	int a = 2;
	printf("%d\n", sizeof(s = a + 5));
	printf("%d\n", s);
	return 0;
}

运行结果是:

为什么会是上述结果呢?

     sizeof(s = a+5)   sizeof()  在()内部的这个表达式是不计算的,因为只要它是一个表达式,一定能计算出一个结果,同时他的类型可以推导出来,不需要再进行计算,s=a+5这个表达式的结果由s决定,s是short类型的,short类型所占的字节数为2,所以 sizeof(s = a+5)的结果就是2,而由于sizeof()  在()内部的这个表达式是不计算的,所以s依然等于10.

6.3 & 与 * 操作符

   在创建变量的时候,我们需要在内存中开辟一块内存空间,开辟空间就会有地址。

   在为变量开辟空间之后,我们可以通过&操作符知道变量的地址。

   在知道变量地址的情况下,想要访问变量中的元素,我们可以使用*(解引用)操作符。

下面通过具体的代码示例来看:

#include <stdio.h>
int main()
{
	int a = 3;
	int* pc = &a;     //& - 取地址操作符
	printf("&a = %p\n", &a);
	*pc = 5;    //解引用操作符         找到地址指向的变量
	return 0;
}

 七、关系操作符

>

>=

<

<=

!=                   用于测试“不相等”

==                  用于测试“相等”

注意:==不能比较两个字符串的内容,他实际上比较的是2个字符串的首字符的地址。

八、逻辑操作符

&&                                    逻辑与(两个操作数同时为真,才为真)

||                                       逻辑或(两个操作数中有一个为真,就为真)

在逻辑操作符计算出的结果,如果计算为真就1,如果计算为假就为0。

举例:

   上述条件中第一个a&&b成立,会打印;第二个a&&b不成立,不会打印。

   在这里,对于这两个操作符我们需要注意的点是:&&与||可能会出现短路的情况。

   if(a&&b) 如果a为假的时候,就不会判断b了,a为假的时候就已经知道表达式的结果了。

   if(a||b)如果a为真的时候,就不会去判断b了,a为真的时候就已经知道表达式的结果了。

我们来看几道典型的例题: 

#include <stdio.h>
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	printf("a = %d\n b = %d\n c = %d\n d = %d\n", a, b, c, d);
	return 0;
}

 他的输出结果是什么呢?

为什么会是这样呢?下面我们来进行解释:

 九、条件操作符

exp1 ? exp2 :exp3

       条件操作符,如果表达式1(exp1)的结果为真,表达式2(exp2)的结果是整个表达式的结果,如果表达式1(exp1)的结果为假,表达式3(exp3)的结果是整个表达式的结果。

代码举例:

int main()
{
	int a = 3;
	int b = 0;
	if (a > 5)
	{
		b = 3;
	}
	else
	{
		b = 9;
	}
}

上述的代码相当于:
 

int main()
{
	int a = 3;
	int b = 0;
	b = ((a > 5) ? 3 : 9);
}

十、逗号表达式

exp1,exp2,exp3,...... expN

逗号表达式就是用逗号隔开的多个表达式。

逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

代码举例:

int main()
{
	int a = 1;
	int b = 2;
	int c = (a > b, a = b + 10, a, b = a + 1);
	//c=13,从左向右依次计算,a > b, a = b + 10 = 12, a, b = a + 1 = 13
}

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

11.1 [ ]下标引用操作符

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

注意:

int arr[10];    //创建数组

arr[9] = 10;      //实用下标引用操作符

[ ]的两个操作数是arr和9.

11.2 ()函数调用操作符

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

例如:

void text(int x, int y)
{
   printf("%d %d",x,y);
}
int main()
{
   text(3,4);
  
}

在上述的代码中,text(3,4); ()就是函数调用操作符,他的操作数是text,3, 4。

11.3 访问一个结构体成员

.     结构体.成员名

->   结构体指针->成员名

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值