小边同学强势总结之c语言操作符(代码片段)

小边同学:) 小边同学:)     2022-12-21     731

关键词:

引:

操作符这部分内容呐,在小边眼里,是看似食之无味,弃之又非常非常可惜的一部分,而且其实是蛮有意思的。
这么讲是因为我个人认为,学校老师把它打散散布在零星各处又不够深入,而如果出题又可能“刁钻”,所以今天拿出来好好总结一下。

正文开始@边通书

一、操作符分类

二、算术操作符

+,-,* 都非常简单,唯一要注意的两点就是 乘 * 和 取模 %

除号 /


运行结果:

取模 %(整除之后求余数)

三、移位操作符

移位操作符移动的都是 内存中的 二进制位。
其实对于整数的二进制位有3种表示方法:原码反码补码,整数在内存中存储的都是补码


呀,怕小伙伴忘记先说一下,最高位也就是符号位,正数为0,负数为1奥。

左移操作符<<(相对简单)

1.左移原理剖析

1.左移正数a:

运行结果:

2.左移负数c:

运行结果

2.右移原理剖析

右移操作符>> (其实也没夺复杂啦)

(1)右移正数a:


运行结果:

(2)右移负数a:


运行结果:

可见,vs2013采用的是算术右移(即补符号位),或者说大多数编译器都采用算术右移。
且,算术右移似乎更合适一些,你是负数,右移之后仍为负数。

3.注:

可爱同学写的胡乱代码,如下


四、位操作符

1.原理剖析

按位与&

按位或|

按位异或^

2.典例

那么这些位操作符到底有什么用呢?下面看:

典例1:计算某整数存储在内存二进制位中有多少1?

1.方法一:

代码:

#include<stdio.h>

int main()

	int a = 15;
	int count = 0;
	int i = 0;

	for (i = 0; i < 32; i++)
	
		if (((a >> i) & 1) == 1)
		
			count++;
		
	

	printf("%d\\n", count);
	return 0;

运行结果,如我所愿:

3.变态面试题

一道变态的面试题:不创建临时变量(第三个变量),实现两个数交换。

我们最最简单也是最常用的办法:

方法一:加减法

运行结果:

此方法虽满足不创建临时变量的要求,但是有一定问题的:
如果a,b都很大且还在int范围之内,buta = a + b很有可能溢出。依然不是最好的解决方案。

方法二:异或的方法

#include<stdio.h>

int main()

	int a = 3;
	int b = 5;

	a = a^b;
	b = a^b;
	a = a^b;

	printf("a = %d,b = %d\\n", a, b);
	return 0;

运行结果:

原理剖析:
异或这个操作符是很有意思的,它让我想起了集合论与图论里的对称差,那个小三角符号。

然而这种方法实际用的比较少:原因:
1.代码可读性不好,乍一看都不知道什么意思
2.只适用于整形
3.且执行效率低
优点是满足了面试官的需求哈哈哈哈。

五、赋值操作符

赋值操作符是一个很棒的操作符,可以让你得到一个之前不满意的值。
1.连续赋值

2.复合赋值符
a += 2;即为a = a + 2;
a >>= 1;即为a = a>>1;
a &= 1即为a = a & 1,
显然前者更加简洁。

类似的有这些:

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

六、单目操作符

单目操作符:即为只有一个操作数的操作符

逻辑反!

一般使用场景如下:

正号+ 负号-

比较简单,不多讲

取地址& 解引用*

sizeof

1.作用剖析 与 strlen()简单对比

运行结果:

2.sizeof是操作符,不是函数
面试官问你:“小伙子,sizeof是不是函数?”,你说,“是!”,面试官“孩子,回家吧。”哈哈哈哈哈

下面用代码简要说明一下:

3.sizeof 内部的表达式是不参与真实运算的
看看以下代码,小伙伴们觉得结果是什么?

#include<stdio.h>

int main()

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

运行结果:

原理剖析:

4.sizeof与数组
读以下代码,给出你的结果:

#include <stdio.h>

void test1(int arr[])

 	printf("%d\\n", sizeof(arr));//(3)

void test2(char ch[])

 	printf("%d\\n", sizeof(ch));//(4)

int main()

	 int arr[10] = 0;
	 char ch[10] = 0;
	 printf("%d\\n", sizeof(arr));//(1)
	 printf("%d\\n", sizeof(ch));//(2)
	 test1(arr);
	 test2(ch);
	 return 0; 
 

原理剖析:

运行结果:
32位平台:

按位取反~

二进制位全部取反,连符号位也要取反!!!
1.上代码感受一下

运行结果:

调试窗口,看看内存中~a的真实存在:

2.应用场景

++,- -

1.前置++

运行结果:

2.后置++

运行结果:

前置- -,后置- -,都同理,不赘述。
3.不建议研究过于复杂的相关代码

在vs下,运行结果为12;
然而在Linux平台下,gcc编译器算出结果为10,
那么这段代码本身就是错误的,就没有什么必要纠结,也不要写这样的代码。
至于为什么出现这种情况,后文会讲。

强制类型转换(类型)

七、关系操作符

同类型 的变量之间 比较大小,比较简单,不做赘述

<,>,<=,>=,==,!=

八、逻辑操作符

关注的是真假。

&&,||

1.逻辑与&&
360笔试题:逻辑操作符的短路效果

#include <stdio.h>
int main()

    int i = 0,a=0,b=2,c =3,d=4;
    i = a++ && ++b && d++;
    //i = a++||++b||d++;
    printf("a = %d\\n b = %d\\n c = %d\\nd = %d\\n", a, b, c, d);
    return 0; 

程序运行结果为多少?

剖析:左为假,则右边不再计算

举一反三:若将a的初值赋为1呐?

运行结果:

2.逻辑或||
完全类似的题目:

运行结果:

举一反三:若将a初值再改成0呐?

运行结果:

九、条件操作符

(exp1) ? (exp2) : (exp3)

十、逗号表达式

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

运行结果:

应用:

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

1.下标引用


进一步说明[ ] 是操作符:

运行结果:

2.函数调用

3.结构成员


上代码加强理解:

运行结果:

注:

十二、表达式求值

操作符可以说是为表达式而服务的,也影响着表达式的结果,主要体现在以下两方面:
1.表达式求值的顺序 ~ 操作符的优先级结合性
2.类型转换 ~ 操作数在求值过程中可能需要转化为其他类型

1.隐式类型转换

隐式,即偷偷地,没法实在地看到。
这里要提到整形提升的概念及意义。

1.整形提升是什么

C的整型算术运算总是至少以缺省整型类型的精度来进行的。
为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
整形提升规则,按照数据类型的符号位来提升。

2.整形提升的意义
小边从来不喜欢贴大段文字,但在这里觉得很有必要,有助于理解为什么要整形提升。

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
一般就是int的字节长度,同时也是CPU的通用寄存器的长度
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

这可能也是寄存器读写很快的原因。

上代码感受:
看看你觉得结果是多少?

#include<stdio.h>

int main()

	char a = 3;
	char b = 127;
	char c = a + b;
	printf("%d\\n", c);
	return 0;

运行结果:

有了前面的铺垫,看到这个结果也不会感到震惊。

原理剖析:


巩固练习1:

#include<stdio.h>

int main()

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

运行结果:只打印c

原理剖析:

巩固练习2:

运行结果:

2.算术转换

寻常算数转换:如果某个操作符的各个操作数属于不同的类型,那么其中一个操作数的必须转换为另一个操作数的类型,否则操作就无法进行。

代码感受:

转换规则:

3.操作符属性


关于优先级,这里值提供部分,有个感觉就好,记不住就加括号:

4.一些问题表达式

那是不是掌握了操作符的优先级及结合性及是否控制求值顺序,就一定能得到表达式的唯一结果了呐?也不是滴。下面来看一些问题表达式。

(1)代码1

a*b + c*d + e*f;

由于*+的优先级高,只能保证,*的计算是比 +早,但是优先级并
不能决定第三个*比第一个+早执行。变量之间的牵连,会导致结果可能不同。

(2)代码2:

(3)代码3:

不同编译器下跑出结果不同:
求值应有唯一路径,那么这样代码就没什么意义。

(4)代码4


(5)代码5
很早小边就拿出过这段代码了

Linux平台下,编译结果

vs2013平台下,编译结果

调试起来,转到反汇编,简单看看即可:

本文完

相信小伙伴们会收获满满的。

关于c语言操作符的总结(代码片段)

整理了一些C语言中的操作符,简单介绍了一下部分重要操作符,也算学习操作符的一些收获吧。一、C语言操作符分类算数操作符、移位操作符、位操作符、赋值操作符、单目操作符、关系操作符、逻辑操作符、条件操作符二、... 查看详情

初识c语言之二(代码片段)

...、注释三、选择语句四、循环语句五、函数六、数组七、操作符算数操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号表达式下标引用、函数调用和结构成员结语:前言:距离上次更新已... 查看详情

初识c语言之二(代码片段)

...、注释三、选择语句四、循环语句五、函数六、数组七、操作符算数操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号表达式下标引用、函数调用和结构成员结语:前言:距离上次更新已... 查看详情

05新手之章——c语言的基本要素(代码片段)

...#xff01;求和代码 目录        序言求和代码 目录四、操作符什么是操作符①算数操作符②位移操作符③位操作符④赋值操作符⑤单目操作符⑥关系操作符⑦逻辑操作符⑧条件操作符⑨逗号 查看详情

五c语言之操作符(代码片段)

目录1、各种操作符的介绍。1.1操作符1.1.1 算术操作符 1.1.2 移位操作符1.1.3位操作符1.1.4赋值操作符1.1.5复合操作符1.1.6单目运算符1.1.7关系操作符1.1.8逻辑操作符1.1.9条件操作符1.1.10逗号表达式1.1.11 下标引用、函数调用和结构成... 查看详情

c语言重点篇:近万字总结文件操作函数(代码片段)

C语言重点篇:近万字总结文件操作函数铺垫知识什么是文件文件名文件类型文件缓冲区文件缓冲系统为什么存在文件缓冲区文件指针相对路径和绝对路径文件的打开方式文件操作函数(顺序读写的)字符输入输出函... 查看详情

c语言-常用寄存器位操作总结(代码片段)

STM32学习笔记-常用寄存器操作常用的寄存器位操作总结1.常用的位操作操作含义&与相同为1,不同为0|或不同为1,相同为0^异或相同为0,相异为1~取反0变1,1变0<<左移左移若干位,高位丢弃,低位补0>>右移右移若干位,... 查看详情

c语言常见文件操作函数总结详解(代码片段)

大家好,我是KookNut39,在CSDN写文,分享一些自己认为在学习过程中比较重要的东西,致力于帮助初学者入门,希望可以帮助你进步。最近在更新C/C++方面的知识,感兴趣的欢迎关注博主,可以去... 查看详情

c语言常见文件操作函数总结详解(代码片段)

大家好,我是KookNut39,在CSDN写文,分享一些自己认为在学习过程中比较重要的东西,致力于帮助初学者入门,希望可以帮助你进步。最近在更新C/C++方面的知识,感兴趣的欢迎关注博主,可以去... 查看详情

c语言之简单使用互斥锁实现并发控制操作(代码片段)

...内容主要为测试使用互斥锁实现并发控制效果,分析C语言中线程并发2.不加锁的并发代码#include<stdio.h>#include<stdlib.h>//从unistd中导入sleep函数#include<unistd. 查看详情

热榜!!!数据结构与算法:c语言版---数组与稀疏矩阵---强势来袭!(代码片段)

数组是各种计算机语言中经常使用到的重要数据结构,一般的说:在内存中申请一片连续地址的存储空间、存储这些数、就称为数组。在C语言中,申请连续的存储空间是很容易的事情,但难在多维数组的组织、以... 查看详情

2019年下c语言课程学期总结(代码片段)

...大一部分原因。前面两次课就发现了老师会在课堂上要求同学们用笔写下一些思路或者代码,而我不知道 查看详情

c语言学习内存操作函数之------->memcpymemmove详解与手动实现(代码片段)

内存操作函数一、memcpy二、memmoveC语言中有时需要对内存空间进行操作,下面详解三个常用的内存操作函数函数memcpymemmove一、memcpy1.memcpy函数简介memcpy——————————参数(void*destination,constvoid*source,size_tnum)返回值void*作... 查看详情

课程设计必备之数据库操作代码模板

课程设计必备之数据库操作代码模板日常总结知识点,加深自身理解,帮助他人学习,欢迎关注我!学计算机专业的大学生们必定会遇到各种各样的课程设计,C语言课程设计、C++课程设计、Java课程设计、数据库课程设计等等。C... 查看详情

c语言九十五之实现经典的反转数组(通过指针或数组下标操作)(代码片段)

1、题目实现反转数组比如数组inta[]=1,2,3,4,5;反转后得使得数组是这样inta[]=< 查看详情

初识c之五花八门的操作符2(代码片段)

操作符2前言一、操作符回顾二、初窥门径(续)5.单目操作符6.关系操作符7.逻辑操作符8.条件操作符9.逗号表达式10.下标引用操作符总结前言上一节我们讲了四种操作符,今天我们来继续补充剩下的一些操作符。一、... 查看详情

javascript总结之数组操作(代码片段)

  JavaScript的数组Array可以包含任何数据类型,并通过索引来访问每个元素。例如要获得数组Array的长度,可以直接访问数组Array的length属性:vararr=[1,6,true,null,9,‘hello‘];arr.length;//返回6若直接给数组Array的length赋予一个新的值会... 查看详情

c语言九十六之实现经典的字符串反转(通过指针或下标操作)(代码片段)

...ars[10]="edcba";可以使用指针或者数组下标实现2、温馨提示C语言试题汇总里可用于计算机二级C语言笔试、机试、研究生复试中C程序设计科目、帮助C语言学者打好程序基础、C语言基础,锻炼您的逻辑思维和解决问题的能力,帮助... 查看详情