C语言_干翻操作符_含义+结合性+优先级+例子分析

操作符知识比较杂乱,这里我按照优先级从高向低的顺序进行整理,优先度越高运算中约先进行

由于本人能力有限,有一些遗漏或者错误还希望大家斧正

优先度最高((),[ ],->,.)

1,( )操作符
含义:函数调用操作符。

操作数是函数名以及函数内部的传参数。

eg: test()操作数是函数名test。
test(x,y)操作数是test ,x,y(函数名+内部的传参数)

注意函数调用操作符只要是函数就必须有

eg: sizeof()的括号可以省略,说明sizeof不是函数,是一种操作符。

强制类型转化
(强制转化类型)

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

在这里插入图片描述

结合性(同优先级操作符在语句中的“运算优先级(或叫顺序) 从左向右。

2,[ ]操作符

含义:下标运算操作符

eg:
arr[4] 操作数为arr和4。

结合性:从左向右

3,->操作符

含义:指向结构体成员操作符。

eg:

#include<stdio.h>
struct student
{
    
    
	//结构体的成员
	char name[20];
	int age;
	char sex[5];
};
int main()
{
    
    
	//结构体访问操作符是建立在结构体上的
	struct student s = {
    
     "小红",18,"woman" };//初始化结构体
	struct student* ps = &s;
	/*printf("%s",(*ps).name);*/
	printf("%s",ps->name);
	return 0;
}

在这里插入图片描述

作用:通过指针找到结构体变量中的成员。

结合性:从左向右。

4, . 操作符

含义:结构体成员运算符。

eg:

#include<stdio.h>
struct student
{
    
    
	//结构体的成员
	char name[20];
	int age;
	char sex[5];
};
int main()
{
    
    
	//结构体访问操作符是建立在结构体上的
	struct student s = {
    
     "小红",18,"woman" };//初始化结构体
	printf("%s",s.name);
	return 0;
}

在这里插入图片描述

#include<stdio.h>
struct student
{
    
    
	//结构体的成员
	char name[20];
	int age;
	char sex[5];
};
int main()
{
    
    
	//结构体访问操作符是建立在结构体上的
	struct student s = {
    
     "小红",18,"woman" };//初始化结构体
	struct student* ps = &s;
	printf("%s",(*ps).name);
	return 0;
}

在这里插入图片描述

用来找到结构体变量中的成员。

结合性:从左到右

优先级2级(!,~,++,- -,-(负号),*(指针),&(取地址),sizeof)

1,!操作符

含义:逻辑非运算(单目运算符)

由真到假,由假到真(0为假,非0为真默认为1)

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

在这里插入图片描述

数据的多组输入

#include <stdio.h>

int main()
{
    
    
	int x = 0;
	while (scanf("%d", &x) != EOF)
	{
    
    
		if (x >= 140)
			printf("Genius\n");
		else
			printf("Not Genius\n");
	}
	return 0;
}

在这里插入图片描述
(文件读取到最后返回一个EOF,EOF本质是-1为真,!EOF为0,程序就会停下来来实现多组输入)

在判断语句中使用

#include <stdio.h>
int main()
{
    
    
	int input = 0;
	if (!input)//如果input为假执行
	{
    
    
		//....
	}
	if (input)//如果input为真执行
	{
    
    
		//....
	}
	return 0;
}

结合性:从右向左

2, ~操作符

含义:按位取反运算符(单目操作符)
(按二进制位取反)

方法:

真变假,假变真。

在二进制位中0变1,1变0;

-----------------------------------------------------------------

首先我们要知道

整数在计算机中存的是它的补码

原码——>反码——>补码

三者的运算规则为

原码按位取反(符号位不变)——>反码。

反码+1——>补码。

在32位计算机中首位是符号位
表示正负不表示大小。

首位为1表示负数,首位为0表示正数。

eg(都是32位)

10000000000000000000000000000001表示-1

00000000000000000000000000000001表示1

对于正整数规定,它的原码,反码,补码都相同可以直接用。

对于负数计算机存的补码不等,要转成原码才可以直到其大小。

eg:
1 1 1 1 1…1 1(32位)(符号位1说明是负数)补码

1 1 1 1 1…1 0(32位)(补码-1到反码)

1 0 0 0 0…0 1(32位)(符号位不变其余位按位取反到原码)

原码首位为1说明是负数,发现值数字-1。

-----------------------------------------------------------------

所以-1在计算机中储存的是32个1

-1取反为32个0是0

而文件读取失败返回EOF本质是-1

0在计算机会判断为假

所以连续输入还可以写为

int main()
{
    
    
	int x = 0;
	while (~scanf("%d", &x) )
	{
    
    
		if (x >= 140)
			printf("Genius\n");
		else
			printf("Not Genius\n");
	}
	return 0;
}

3,++操作符

含义:自增运算符(单目操作符)

分为前置++和后置++(他们运算顺序不同)

前置++

先++再在使用。

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

在这里插入图片描述

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

在这里插入图片描述

后置++

先使用再++

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

在这里插入图片描述

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

在这里插入图片描述

这里因为是先使用所以a没有自增就被打印了出来。

结合性从右向左

4,- -操作符

含义:自减运算符(单目运算符)

分为前置- -和后置- -

前置- -

先- -再使用

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

在这里插入图片描述

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

在这里插入图片描述
后置- -

先使用再- -

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

在这里插入图片描述

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

在这里插入图片描述

这里因为先使用所以a还没有自减就已经被打印

5,-符号运算符

含义:负号运算符(单目运算符)

优先级:从右向左

(注意负号运算符和减法运算符不同,负号运算符是单目运算符,减法运算符是双目运算符,系统会自动识别)

#include <stdio.h>
int main()
{
    
    
	int a = 10;
	a = -a;//负号运算符
	a = a - 10;//减法运算符
	return 0;
}

6,* (指针)操作符

含义:指针运算符(单目运算符)

用来存放地址,或者找到指针变量所指对象。

(具体指针性质在之后提到)

#include <stdio.h>
int main()
{
    
    
	int a = 5;
	int* pr = &a;//存放地址
	printf("%d",*pr);//找到指针变量所指对象
	return 0;
}

在这里插入图片描述
结合性:从右向左

7,&(取地址)操作符

含义:地址运算符(单目操作符)

结合性:自右向左

通常伴随指针使用不再赘述

8,sizeof 操作符

含义:长度运算符(单目操作符)

sizeof可以计算变量大小,也可以计算变量类型大小
在这里插入图片描述
(注意int[10]是数组的类型)

当求变量大小时sizeof()括号可以省略

但当求到变量类型的大小时括号不可以省略

在这里插入图片描述
sizeof与strlen的区别

sizeof是操作符求大小,strlen是求字符串长度函数其必须有()函数调用操作符

sizeof会计算\0的大小,而strlen不会计算\0的长度(\0)是字符串结束的标志。

sizeof括号内的表达式是不会执行计算的

eg:

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

在这里插入图片描述
发现s在sizeof()内却没有计算,sizeof只计算了s类型的大小
(注意这个例子中决定sizeof值的是s的类型不是表达式中a的类型)

不计算的原因是
我们编译的.c文件会经过链接生成.exe可执行文件
而sizeof(s=a+5)在编译过程中就被替换成s类型的大小,所以就相当于s=a+5这个表达式在exe文件中是2,所以不会i执行运算

结合性:从右向左

优先级3级(*(乘法),/,%)

1.*(乘法),/,%操作符

*(乘法)操作符 运算不在赘述;

/(除法)操作符
(注意要想通过除法得到一个浮点型,除数与被除数至少有一个要写出小数)

#include <stdio.h>
int main()
{
    
    
	float i = 3 / 2.0;
	printf("%f",i);
	return 0;
}

%(求余操作符)
(注意%不能有小数)

通常通过%来控制随机数的范围,
或者得到数字的每一位,
也可以通过%2来得到数字二进制的每一位。

三者结合性:从左向右。

优先度4级(+,-(减))

1.+操作符

含义:运算(不在赘述)

2.-操作符

含义:减法运算符

(注意与负号运算符区分即可不再赘述)

二者的结合性:从左向右。

优先度5级(<<,>>)

1,<<操作符

含义:左移操作符(移动的是储存在内存中二进制的补码)

规则:左边丢弃,右边补零。

#include <stdio.h>
int main()
{
    
    
	int a = -1;
	a = a << 1;
	printf("%d",a);
	return 0;
}

分析:
-----------------------------------------------------------------

首先我们要知道

整数在计算机中存的是它的补码

原码——>反码——>补码

三者的运算规则为

原码按位取反(符号位不变)——>反码。

反码+1——>补码。

在32位计算机中首位是符号位
表示正负不表示大小。

首位为1表示负数,首位为0表示正数。

eg(都是32位)

10000000000000000000000000000001表示-1

00000000000000000000000000000001表示1

对于正整数规定,它的原码,反码,补码都相同可以直接用。

对于负数计算机存的补码不等,要转成原码才可以直到其大小。

eg:
1 1 1 1 1…1 1(32位)(符号位1说明是负数)补码

1 1 1 1 1…1 0(32位)(补码-1到反码)

1 0 0 0 0…0 1(32位)(符号位不变其余位按位取反到原码)

原码首位为1说明是负数,发现值数字-1。

-----------------------------------------------------------------
a的二进制值在内存中为32个1

在这里插入图片描述
移动后
补码变成1 1 1 1 1 …0(32位)
反码 1 1 1 1 1…01(32位)
原码 1 0 0 0 0…10(32位)
翻译原码是-2

在这里插入图片描述
结合性:从左向右。

2.>>操作符

含义:右移操作符

有两种移动方式

1,算数右移
2,逻辑右移

算数右移:右边丢弃,左边补充符号位。

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

在这里插入图片描述

在这里插入图片描述
vs2019使用的是算数右移

注意不要移动负数位
eg:
a=a>>-1(这种写法编译器不支持)

结合性:从左到右。

优先度6级(<,>,>=,<=,)

用于比较两个数字的关系(这里不再赘述)

结合性:从左到右

优先度7级(==,!=)

1.==操作符

含义:判断两个值是否相同

注意(在C语言中一个等号是赋值,两个等号是判断是否相同。)

==判断是否相同时不能判断字符串与字符串相同

判断字符串相同用的是strcmp函数

结合性:从左向右

2,!=不等于操作符

结合性:从左向右

不在赘述

优先度8级(&(按位与),|,^)

1,&(按位与)操作符

方法:按照二进制位与

#include <stdio.h>
int main()
{
    
    
	int a = 6;
	int b = 4;
	int c = a & b;
	printf("%d",c);
	return 0;
}

注意a,b的二进制位是32位的,这里因为篇幅有限只写出有效部分

&相当于求交集,二进制位1代表真,0代表假
只有同时为真的时候按位的结果才为1,其余情况全部为0

a的二进制位 0 1 1 0
b的二进制位 0 1 0 0
-----------a&b 0 1 0 0

因为是正数,原码=反码=补码
翻译结果为4

在这里插入图片描述
结合性:从左到右。

2,| 按位或操作符

方法:
按位或相当与并集,只要二进制位上有1,则最后按位或的结果就为1.

#include <stdio.h>
int main()
{
    
    
	int a = 6;
	int b = 4;
	int c = a | b;
	printf("%d",c);
	return 0;
}

a的二进制位 0 1 1 0
b的二进制位 0 1 0 0
------------a|b 0 1 1 0

发现a|b的结果与a相同为6
在这里插入图片描述
结合性:从左到右

3,^ 按位异或操作符

方法:二进制位相同是为0,二进制位不同为1

#include <stdio.h>
int main()
{
    
    
	int a = 6;
	int b = 4;
	int c = a ^ b;
	printf("%d",c);
	return 0;
}

a的二进制位 0 1 1 0
b的二进制位 0 1 0 0
-----------a^b 0 0 1 0

翻译后为2
在这里插入图片描述

优先度9级(&&,| |)

1,&& 逻辑与操作符
(注意与&区分,&&不是在二进制上来考虑的,只关心真假)

在C语言中 0为假,非0为真,且计算机输出的真值默认为1.

相当于交集

#include <stdio.h>
int main()
{
    
    
	int a = 6;
	int b = 4;
	int c = a &&b;
	printf("%d",c);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
(注意逻辑与操作可能会出现短路现象)

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

在这里插入图片描述

分析:在这里插入图片描述
当把a改为1时就会正常

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

在这里插入图片描述

应用:
在 if 语句中使用if(a>1&&a<3)

表示 1<a<3;

结合性:从左到右

2,| | 逻辑或运算符
(同理也要和 | 区分)

相当于并集

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

在这里插入图片描述
同理注意逻辑或也存在短路现象

int main()
{
    
    
	int i = 0, a = 1, b = 2, c = 3, d = 4;
	i = a++||++b || d++;
	printf("a=%d b=%d c=%d d=%d i=%d",a,b,c,d,i);
	return 0;
}

在这里插入图片描述

其原理与逻辑与相同

因为逻辑或前一个表达式为真则一定为真,所以编译器会让++b和d++都不执行,只执行了a++

应用:

用在 if 语句中
if(a>2||a<0)表示a>2或者a<0

结合性:从左向右。

从上面的分析可知&& 与| |都是会控制求值顺序的

优先度10级(?:)

1,?: 条件操作符

三目操作符

格式:
表达式?成立时:不成立时

应用:代替if…else使代码量减少

eg:求三个数最大值

#include <stdio.h>
int main()
{
    
    
	int a = 0, b = 0, c = 0;
	scanf("%d%d%d", &a, &b, &c);
	int max = a > b ? a : b;//先比较a,b成立max=a不成立max=b;
	int max2 = max > c ? max : c;//在于c比较大于c则max是最大值,否则c是最大值
	printf("最大值是%d",max2);
	return 0;
}

在这里插入图片描述

优先级:从右向左

优先级11级(=,+=,-=,*=,/=,%=,>>=,<<=,&=,^=,|=)

1,=
C语言中=是赋值操作,不在赘述

2,a+=1——a=a+1
其余的类似不在赘述

结合性:从右向左

优先级12级(,(逗号表达式))

1, , 逗号运算符(顺序求值操作符)

含义:用逗号隔开的多个表达式,从左向右依次进行,整个表达式的结果就是最右边表达式的结果。
(括号内的表达式都会计算)

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

a=12 c=b=a+1=13
在这里插入图片描述

应用:使代码简洁

while(a>0)                 while(a=fun(),a>0)
{
    
                              {
    
    
  表达式1;    可以写成        表达式1;
  表达式2;                   表达式2;
  a=fun();                  }
}

结合性:从左到右。

猜你喜欢

转载自blog.csdn.net/dodamce/article/details/113186781
今日推荐