当前位置:首页 » 《随便一记》 » 正文

操作符小结_benxiangsj的博客

25 人参与  2022年05月25日 16:15  分类 : 《随便一记》  评论

点击全文阅读


引入:

操作符是一个表示特定的数学或逻辑操作的符号,如数学中的加法,在c语言中也有+,而c语言中不止有加减乘除,通过本小节来学习并了解和学习这些操作符。

一、操作符分类

算数操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

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

二、详细介绍操作符

1.算数操作符

+     -     *    /     %

加减乘和数学中的运算符用法一样,这里重点介绍  /  和  %(取模)

1)对于 / 操作符,如果两个操作数都为整数,执行整数除法;而只要有浮点数,执行的就是浮点数除法。这句话理解如下:

int main()
{
	int a = 10 / 3;
	double b = 10.0 / 3;
	double c = 10 / 3.0;
	printf("a=%d\n", a);  //结果为3,因为10和3都是int型
	printf("b=%lf\n", b); //结果为3.333333,因为10.0是double型
	printf("a=%lf\n", c); //结果为3.333333,因为3.0是double型

	return 0;
}

2)% 的意思是求余,如10%3的结果为1,因为10除以3的余数是1。

%操作符的两个操作数必须为整数,如10.0%3这样的写法就是错误的。%返回的是整除后的余数

2.移位操作符

1)引入:在介绍移位操作符之前,我们先介绍整数在内存中如何存储的

整数有三种二进制表示形式:原码、补码、反码。

整数在内存中存储的是补码

正数的原码、反码、补码

如 int a = 5,a是整型,占内存的4个字节,即32bit。5用二进制表示是101,因为占32个bit,所以将它补全即为 00000000 00000000 00000000 00000101 ,这个就是5的原码

正数的原码、反码、补码都是这个

负数的原码、反码、补码

如 int a = -5,

5的原码是00000000 00000000 00000000 00000101

-5的原码就是将它的第一位0变成1,即10000000 00000000 00000000 00000101

-5的反码就是将原码的符号位不变,就是第一位不变,其余的0变成1,1变成0

11111111 11111111 11111111 11111010

-5的补码就是反码的二进制+1

11111111 111111111 11111111 11111011

2)  左移操作符

规则:左边抛弃,右边补0

对于正数的左移操作,因为正数的原、反、补码都一样,所以直接将原码左移就可以了。

int main()
{
	int a = 5;
	int b = a << 2;//把a在内存中存储的二进制位向左移动两位
	printf("a=%d b=%d\n",a, b);//a=5,b=20
	return 0;
}

下面画图进行解释,二进制位向左移动两位。

 对于负数的左移操作,需要求出其补码,将补码移位,再将移位后的补码转化为原码,求出其值。因为打印或使用的时候,用的是原码的值。

int a = -5;

int b = a<<2;

11111111 111111111 11111111 11111011    -5的补码

11111111 111111111 11111111 11101100    将-5的补码左移两位

11111111 111111111 11111111 11101011     反码:补码减一

10000000 00000000 00000000 00010100  原码:结果是-20

3)右移操作符

规则:算数右移:右边丢弃,左边补原来的符号位

           逻辑右移:右边丢弃,左边补0

到底是算数右移还是逻辑右移,取决于编译器,我们常见的编译器都是算数右移

对于正数的右移,直接将原码右移,补符号位时补0

int main()
{
	int a = 5;
	int b = a >> 1;
	printf("%d\n", b);//结果是2
	return 0;
}

对于负数的右移和左移相似,也是将其补码右移,唯一区别的就是左边补位的时候,不是补0,而是补符号位1

3.位操作符

1)& 按位与:按(2进制)位与-----两个数的补码对应位只要有0就是0,两个同时为1才为1

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	printf("%d\n", c);//结果是3
	return 0;
}

解释:00000000 00000000 00000000 00000011   3的补码

           11111111   11111111   11111111   11111011    -5的补码

           00000000 00000000 00000000 00000011  按位与后的补码

因为符号位是0,所以这是一个正数的补码,原码和补码相同,所以结果是3

2)|   按位或:按(2进制)位或---两个数的补码对应位只要有1就是1,两个同时为0才为0

int main()
{
	int a = 3;
	int b = -5;
	int c = a | b;
	printf("%d\n", c);//结果是-5
	return 0;
}

解释: 00000000 00000000 00000000 00000011   3的补码

            11111111   11111111   11111111   11111011    -5的补码

            11111111   11111111   11111111   11111011    按位或后的补码,符号位是1,所以是个负数,需要求它的原码

            11111111    11111111   11111111   11111010    按位或后的反码

            10000000   00000000 00000000 00000101   按位或后的原码,即为-5

               

3)^   按位异或:按(2进制)位异或:两个对应位相同为0,相异为1

int main()
{
	int a = 3;
	int b = -5;
	int c = a ^ b;
	printf("%d\n", c); //结果是-8
	return 0;
}

解释:00000000 00000000 00000000 00000011   3的补码

           11111111   11111111   11111111   11111011    -5的补码

           11111111   11111111   11111111   11111000    按位异或后的补码,这是个负数,要求出它的原码

           11111111   11111111   11111111   11110111    按位异或后的反码

           10000000  00000000 00000000 00001000  按位异或后的原码,即为-8

4.赋值操作符

=  用来给变量赋值,如  int  a = 10;

符合赋值操作符

+=

-=

*=

/=

%=

>>=

<<=

&=

|=

^=

复合操作符的使用用法如下:

这里用‘+=’为例

int main()
{
  int a = 0;
  a += 10;  //等价于a = a+10
  printf("a=%d\n",a);//结果为10
  return 0;
}

5.单目操作符

1)!      逻辑反操作 :作用是把假的变成真的,把真的变成假的

int main()
{
  int flag = 0;
  if (!flag)  //因为flag为0是假,!flag为真,进入if语句
  {
    printf("我爱c语言\n");
  }
  return 0;    //打印我爱c语言
}
  

2)-      负值

例:在屏幕上打印 0 -1 2 -3 4 -5 6 -7 8 -9

int main()
{
	int i = 0;
	int flag = 1;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", i * flag);
		flag = -flag;
	}
	return 0;
}

3)+     正值 

4)&     取地址:拿取在内存中的地址

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

int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));//结果是4,因为int是整型,整型占四个字节
	printf("%d\n", sizeof(int));//结果是4
	int arr[10] = { 1,2,3,4,5,6 };
	printf("%d\n", sizeof(arr)); //结果是40   计算整个数组的大小
	printf("%d\n", sizeof(int [10]));//结果是40,数组里有10个int型,所以是40
	return 0;
}

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

int main()
{
	int a = 0;
	//00000000 00000000 00000000 00000000 这是0的补码
	//11111111 11111111 11111111 11111111 这是按位取反后的结果,这个依然是补码
	//11111111 11111111 11111111 11111110 这是反码
	//10000000 00000000 00000000 00000000 这是原码,是~a最后的结果,即是-1
	printf("%d\n", ~a);//结果是4,因为int是整型,整型占四个字节
	return 0;
}

7)++    前置、后置++

int main()
{
	int a = 10;
    int b = ++a; //前置++,先++,后使用。即先把a+1,再赋值给b
	int c = 10;
	int d = c++; //后置++,先使用,后++。即先把c的值赋给d,c再+1
	printf("a=%d b=%d\n",a, b); //a = 11 b = 11
	printf("c=%d d=%d\n",c, d);//c = 11 d = 10
	return 0;
}

8)--      前置、后置-- :和上面相似,就不多做介绍了。

9)*       间接访问操作符(解引用操作符):对地址进行解引用操作

int main()
{
	int a = 0;
	int* pa = &a;  //pa里面放的是a的地址,*pa找到a的空间
	*pa=20;  //找到a的空间,将a的值改为20
	printf("%d\n", a);  //打印20
	return 0;
}

10)(类型)  强制类型转换

int main()
{
	//int a = 3.14;//3.14是double类型的数据,把它放在int型里会丢失数据,并且会报警告
	int a = (int)3.14;//强制类型转换,将3.14强制转换成int型
	printf("%d\n", a);//结果是3,不会报警告
	return 0;
}

强制类型转化不建议经常使用。

6.关系操作符

1) >     

2) >=

3) <

4) <=

5) !=

6) ==

7.逻辑操作符  

逻辑操作符只关注真假

1) &&   逻辑与:表示并且

例:写一个代码,当从键盘输入一个大于0小于18的数时打印未成年

int main()
{
	int age = 0;
	//if (0 < age < 18)//这种写法是错误的。例如输入20,而20是大于0的,是真,也会进入if中
	//{
	//	printf("未成年");
	//}
	scanf("%d", &age);
	if (age > 0 && age < 18)
	{
		printf("未成年");
	}
	return 0;
}

2)|| 逻辑或:表示或者

例:几个练习

&&  左操作数为假,右边不计算。为真的时候才计算右边

||     左操作数为真,右边不计算。为假的时候才计算右边

int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;//a=0是假,后面就不需要计算了,b、d的值保持不变
	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//a,b,c,d的值分别为1,2,3,4
	return 0;
}
int main()
{
	int i = 0, a = 1, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;//a++是真,右边的++b,d++计算
	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//a,b,c,d的值为2,3,3,5
	return 0;
}
int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ || ++b || d++;//因为++b是真,右边的d++不计算
	printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);//a,b,c,d的结果是1,3,3,4
	return 0;
}

 8.条件操作符(三目操作符)

表达式1 ? 表达式2 : 表达式3:表达式1结果为真,就执行表达式2;为假就执行表达式3

例:利用三目操作符来判断两个数的较大值

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

9.逗号表达式

表达式1,表达式2,..... ,表达式n

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

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

int main()
{
	int a = 3;
	int b = 5;
	int c = 6;
	int d = (a += 2, b = a - c, c = a + 2 * b);
	printf("%d\n", d);//结果是3
	return 0;
}

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

1) [ ] 下标引用操作符

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", arr[6]);//操作数是arr和6,结果是7
    printf("%d\n", 6[arr]);//arr[7] ——->*(arr+6)-->*(6+arr)-->6[arr],结果也是7
	return 0; 
}

2)函数调用操作符

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

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int ret = Add(2, 3);
	printf("%d\n", ret);
	return 0;
}

3.访问一个结构体成员

.     结构体变量.结构体成员

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

struct Stu
{
	char name[20];
	int age;
	double score;
};
int main()
{
	// .
	struct Stu s = {"xiaohong", 19, 95.5};
	printf("%s %d %.1lf\n", s.name, s.age, s.score);
	// ->
	struct Stu* ps = &s;
	printf("%s %d %.1lf\n", (*ps).name, (*ps).age, (*ps).score);
	printf("%s %d %.1lf\n", ps->name, ps->age, ps->score);
	return 0;
}


点击全文阅读


本文链接:http://zhangshiyu.com/post/40746.html

补码  操作  反码  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1