操作符详解!!!讲解剖析-创新互联

---- 操作符分类+剖析----:
  • 1.算术操作符
  • 2.移位操作符
  • 3.位操作符
  • 4.赋值操作符
  • 5.单目操作符
  • 6.关系操作符
  • 7.逻辑操作符
  • 8.条件操作符
  • 9.逗号表达式
  • 10.下标引用、函数调用和结构成员
  • 11.表达式求值

创新互联是一家集网站建设,凤凰企业网站建设,凤凰品牌网站建设,网站定制,凤凰网站建设报价,网络营销,网络优化,凤凰网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。1.算术操作符

算术操作符:
在这里插入图片描述
**1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。

  1. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
  2. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。**
2.移位操作符

在这里插入图片描述
2.1 左移操作符
使用规则:
左边抛弃,右边补0

2.2 右移操作符
使用规则:

逻辑移位 :  左边用0填充,右边丢弃。   

在这里插入图片描述

算术移位 : 左边用原该值的符号填充

在这里插入图片描述

3.位操作符

位操作符有:(这里的位都是二进制位)
这里都是看二进制位喔

& //按位与     0和0还是 0 , 1和0还是0 , 必须两个都为1 才能结合出来1
| //按位或     只要有一个1就能结合出来1啦,而只有;两个0 才能结合出来0
^ //按位异或    相同为0 相异为1
注:他们的操作数必须是整数。
#includeint main()
{int a = 1;
 int b = 2;
 a & b;
 a | b;
 a ^ b;
 return 0;
}

给大家介绍一个比较神奇的代码,它是不创建变量,然后将a,b内容交换。用的正是这里介绍的按位异或^操作符

#includeint main()
{int a = 10;
 int b = 20;
 a = a^b;  //把a^b 看成一个钥匙,它遇到a就能打开b的然后变成b;
 b = a^b;//a相当于钥匙,它遇到b就打开b变成a,然后再赋给b;b就变成a的值了
 a = a^b;//b相当于钥匙,它遇到a就打开a变成b,然后再赋值给a,a值就变成了b值
 printf("a = %d b = %d\n", a, b);
 return 0;
}

编写代码实现: 求一个整数存储在内存中的二进制中1的个数

#includeint main()
{int num  = 10;
 int count=  0;//计数
 while(num)
 {if(num%2 == 1)
 count++;
 num = num/2;//正常思想从如何分解一个数的各个位数,,%10  再/10;
 }
 printf("二进制中1的个数 = %d\n", count);
 return 0;

另一种方法:

#includeint main()
{int num = -1;
 int i = 0;
 int count = 0;//计数
 for(i=0; i<32; i++)
 {if( num & (1<< i) )
 count++; 
 }
 printf("二进制中1的个数 = %d\n",count);
 return 0;
 }

还有没有更好的方法呢?

int main()
{int a = -1;
	int count = 0;
	//怎么更好的计算a的1 的个数呢?
	// a & (a - 1);这种方式可以每次把最右边的1给拿掉;
	while (a)
	{a = a&(a - 1);
		count++;
	}
	printf("1的个数:%d", count);

	return 0;
}

但这种方法实在想不到喔…

4.赋值操作符
看好是一个 = 而不是两个==喔

int a=10;//可以将想要的数赋值
int b=a+10;
复合赋值符

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

5.单目操作符

单目操作符介绍

!           逻辑反操作
 -           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
(类型)       强制类型转
1. sizeof是用来计算变量所占空间的大小   ,它是一个操作符,不是库函数喔。
void test1(int arr[])
{printf("%d\n",sizoeof(arr));
}
void test2(char ch[])
{printf("%d\n",sizeof(ch[]);
}
int main()
{int a = 10;
	char s = 'a';
	int arr[10] = {0 };
	char ch[10] = {0 };
	printf("%d\n", sizeof(a)); //一个整形4个字节
	printf("%d\n", sizeof(s));//1一个字符1个字节
	printf("%d\n", sizeof(arr));//数组10个整形40个字节
	printf("%d\n", sizeof(ch));//数组10个字符10个字节
	test1(arr);//问题1:这个是多少呢?
	test2(ch);//问题2:这个又是多少呢?
	return 0;
}

问题1和问题2其实本质一样,这里把arr和ch传给函数test1和test2,函数传参,这里数组传过去的是首元素地址,也就是相当于指针,而sizeof计算地址大小这个就是由编译器是X64还是X32决定的了,如果是64位的那么大小应该是8,如果是32位的大小应该是4.
在这里插入图片描述

3 .前置++和后置++

前置++: 先++后使用。
后置++:先使用后++。

int main()
{int a = 10;
	int x = ++a;
	//前置++,先将a自增变成11,再使用a,将a赋值给x,x=11;
	printf("a=%d x=%d\n", a, x);
	return 0;
int main()
{int a = 10;
	int y = --a;
	//前置--,先将a自减成9,再使用a,将a赋值给x ,x=9
	printf("a=%d y=%d\n", a, y);
}
int main()
{int a = 10;
	int z = a++;
	    //后置++,先将a赋值给z,z=10,再给a自增+1,a就变成11;
		printf("a=%d z=%d\n", a, z);
	
}
int main()
{int a = 10;
	int v = a--;
		//后置--,先将a赋值给y,y=10,再给a自建-1,a就变成9了;
		printf("a=%d v=%d\n", a, v);
	
}
6.关系操作符
>>=<<=
 !=
 == 注意和一个=的区别
7.逻辑操作符
&&                    逻辑与
 ||                    逻辑或

区别:

逻辑与 -------按位与
逻辑或 -------按位或

1&&2 ---->1(表示真)
1&2   ---->0(二进制进行计算)
1||2   ---->1(表示真)
1|2    ---->3(二进制进行计算)

逻辑与和逻辑或有什么特点呢?
短路求值!
比如逻辑与&&: 表达式1&&表达式2 表达式1为假则右边不再进行。
逻辑或|| : 表达式1||表达式2 表达式1为真则右边不再进行。

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\nd = %d\n", a, b, c, d);
    return 0;
}
因为 i = a++ && ++b && d++;   a++是后置++,先使用后++,所以a=0,先使用与&&进行配对,然后是假,
所以后面++b, d++都不再进行,但a++,这个还是进行的,所以a用完后还要给a+1,
所以a=1,b=2,c=3,d=4;
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\nd = %d\n", a, b, c, d);
    return 0;
}
这里a++(a=0,先使用与||配对为假,再+1,++b,b自增为3与||配对为真,后面的d++不再进行了所以
a=1,b=3,c=3,d=4;
8.条件操作符
表达式1  ? 表达式2 :表达式3               表达式1成立--->最终结果为表达式2,否则为表达式3.

一般条件表达式(if else )可以用条件操作符代替
求两个数中较大值:

int main()
{int a = 10;
	int b = 20;
	int max = (a >b ? a : b);//a表达式1 a>b如果成立那么max=a,否则max = b;
	printf("%d", max);
	return 0;
}
9.逗号表达式
表达式1,表达式2,……表达式n

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

int main()
{int a = 0;
	int b = 1; 
	int c = (a >b, a = b + 10, a, b = a + 1);//逗号表达式
	printf("%d", c);
	//c是多少?
	return 0;
}
虽然结果是最后一个但是前面的逗号表达式还是要进行的,第一个a>b假的,不用管,第二个a=b+10,a=11了,第三个b=a+1,那b就等于12
a = b + 1;
	c = a / 2;
	if (d >0)
	{……
	}
	写成逗号表达式if (a = b + 1, c = a / 2, d >0)
在这里插入代码片
10.下标引用、函数调用和结构成员

1. [ ]下标引用操作符
操作数:一个数组名+一个索引值

int main()
{int arr[5] = {0,1,2,3,4};//创建数组,初始化
	 printf("%d",arr[4]);//arr[4]是等于4
	 arr[4]=10; //使用下标引用改变arr[4]成10
    []操作数是arr和 5
	return 0;
}

2.( )函数调用操作符
接收一个或多个操作数,第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

void test()
{printf("hello\n");
}
void test1(char * ch)
{printf("%s", ch);
}
int main()
{test();
	test1("hello");
	return 0;
}

3. . 访问一个结构的成员

 .      结构体.成员名
     ->结构体指针->成员名
struct Stu
{char name[10];
	int age;
	char sex[5];
	double score;
};
void set_age1(struct Stu stu)
{stu.age = 18;//结构体成员访问 .访问
}
void set_age2(struct Stu* pStu)
{pStu->age= 18;//结构体成员访问,指针访问。
}
int main()
{struct Stu stu;
	struct Stu* pStu = &stu;//结构体成员访问。
	stu.age = 20;//结构体成员访问
	set_age1(stu);
	pStu->age = 20;//结构体成员访问
		set_age2(pStu);
	return 0;
}
11.表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转化成其他类型

11.1.隐式类型转化

C语言算术运算总是至少以缺省型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转化为普通整形,这种转化称为整形提升。
整形提升的意义:

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的 字节长度一般 就是int的字节长度,
同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为 CPU 内整型操作
数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有
这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才
能送入CPU去执行运算
int main()
{char a, b, c;
	a = b + c;//b+c要进行整形提升,b和c的值被提升到普通整形,然后再进行加法运算
	//加法运算完成之后,结果将被截断,然后再存贮到a中。
	return 0;
}

怎么进行整形提升的呢?

整形提升是按照变量的数据类型的符号位来提升的

负数的整形提升

>int main()
{
	char ch = -1;//字符一个字节---8个比特位
	变量ch的二进制位(补码)中只有8个比特位;
	11111111
	因为char为有符号的char
	所以整形提升的时候,高位补充符号位,即为1
	提升之后的结果是:
	11111111111111111111111111111111
	return 0;
}

正数整形提升

int main()
{
char ch = 1;
//变量ch的二进制位(补码中)只有8个比特位
00000001;
因为char 为有符号的char
所以整形提升的时候,高位补充符号位即为0;
提升之后的结果就是:
00000000000000000000000000000001
无符号整形提升,高位补0;
return 0;
}

整形提升的例子1:

int main()
{char a = 0xb6;
	short b = 0xb600;
	int c = 0xb6000000;
	if (a == 0xb6)
	{printf("a");
	}
	if (b == 0xb600)
	{printf("b");
	}
	if (c = 0xb600000)
	{printf("c");
	}
	return 0;
}

结果是什么呢?在这里插入图片描述
这里是因为a和b都要先进行整形提升,而c不需要进行整形提升。
a,b整形提升之后变成了负数,所以表达式,a==0xb6,b= =0xb600为假,c的结果为正,所以只打印c

实例2:

int main()
{char a = 1;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(+a));
	printf("%d\n", sizeof(-a));

	return 0;
}

嘿嘿结果又是多少呢?在这里插入图片描述
神奇嘛?
实例2中的,a只要参与表达式运算的,就会发生整形提升,表达式+a,就会发生整形提升,所以sizeof(+a)就是4个字节。
表达式-a也会发生整形提升,所以sizeof(-a)也是4个字节,但sizeof(a)没有发生整形提升所以是1个字节。

11.2.算术转化
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转化为另一个操作数的类型,否则操作就无法进行,下面的层次体系为寻常算术转化

long double
double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转化为另一个操作数的类型后进行运算

但要注意算术转化要合理,要不然就会存在一些潜在问题
float a=3.14;
int num =a; 在会发生隐式转化,精度丢失

11.3.操作符的属性
复杂的表达式的求值会有三个影响因素:

1.操作符的优先级
2.操作符的结合性
3.是否控制求值顺序。

两个相邻的操作符先执行哪一个?这个取决于他们的优先级,如果两个优先级相同,那再取决与他们的结合性。

操作符优先级:

下面给出详细的操作符的优先级表格,从上至下优先级依次递减(越靠近上面,操作符的优先级越高)

在这里插入图片描述

![在这在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻标题:操作符详解!!!讲解剖析-创新互联
本文地址:http://ybzwz.com/article/dcjdji.html