浅识C语言中那些操作符(保证足够详细)

举报
念君思宁 发表于 2023/02/18 17:54:53 2023/02/18
【摘要】 浅识C语言中那些操作符(保证足够详细)

浅识C语言中那些操作符!(保证足够详细)

在C语言中,有着众多的操作符,如果不能正确认识,那么在书写C语言代码时候,将会遇到这样那样的错误,甚至对于自己写的代码,都不知道bug在哪?更何况,去找bug呢??

因此,我们需要正确的去认识,并且知道每一个C语言操作符所代表的具体含义是什么!这样我们看待代码时候,才不会两眼抓瞎!

下面,笔者将带领大家认识一下,笔者所认识,及所感悟到操作符!!

1.算数操作符:

         +   -  *    /  %

在这里面,算术操作符,算是大家较为了解的操作符,毕竟每一个代码中,或多或少都会用到算术操作符!

但是我们运用时候,还要注意一下几点!

(1).除了%取除操作符之外,其他几个操作符,都可以应用于整数和浮点数

(2).对于/除法操作符,如果两个操作数都为整数,执行整数除法,而只要有小数(浮点数),执行的就是浮点数除法

(3).%取余操作符的两个操作数必须是整数!(很重要)

 笔者亲测,这样将会进行报错!所以不能有这样的写法!

(4)./除法中,要想得到小数(浮点数),则必须保证在除数和被除数之间必须有一个小数(浮点数)

(5),我们还需要注意,加减乘除取余运算符之间的优先级!

2.移位操作符

《  左移位操作符    ;     》  右移位操作符

在这里,我们需要注意的是,移位操作符的操作数,只能是整数(小数,负数都不行),移位负数将没有意义

移位操作符:移动的是二进制位!

下面,我们需要浅浅介绍一下:二进制如何去表达??

如数值15:

在我们计算机中平常输入加使用的都是十进制形式! 

在十进制中:15=1*10的一次幂+5*10的0次幂

在二进制中:15=1*2的3次幂+1*2的2次幂+1*2的一次幂+1*2的0次幂

在八进制中:15=1*8的1次幂+7*8的0次幂

至于其他的进制,由于篇幅原因,笔者将不再进行详细解答!

需要注意的是:10进制的表示为:0~9;

                          8进制的表示为0~7;

                           2进制的表示为0,1;

在二进制中:15=1*2的3次幂+1*2的2次幂+1*2的一次幂+1*2的0次幂

因此15的二进制表示为:00000000000000000000000000001111(一共32位)

原因为:15 是个整数,在C语言中可以存放在int 类型的变量中,而int类型的变量占4个字节(32个比特位)

上面我们已经了解到了进制的表达形式!但是,整型在计算机中的二进制的表达形式.............

整型的二进制的表示有三种:原码,反码,补码!

原码:直接根据数值写出的二进制序列就是原码

反码:原码的符号位不变,其余位按位取反就是反码

补码:反码+1就是补码

符号位:

                   开头的第一位就是符号位!

                   符号位位0:表示正数

                   符号位位1:表示负数

因此,对于15来说:(正数的原码,反码,补码相同)

00000000000000000000000000001111          15的原码

00000000000000000000000000001111           15的反码

00000000000000000000000000001111         15的补码

对于-15来说:(注意符号位的改变)

10000000000000000000000000001111            -15的原码

111111111111111111111111111111110000           -15的反码(原码的符号位不变,其余位按位取反就是反码)

111111111111111111111111111111110001           -15的补码(反码+1)

移位操作符:移动的是存储在内存中的补码!

当a=4时:

#include <stdio.h>
int main()
{
	int a = 4;
	//a的补码00000000000000000000000000000100
	int b = a << 1;
	//把a向左移动1位
	printf("a=%d  b=%d\n", a, b);
	return 0;
}

在这里,我们来看一下代码的运转结果:

 对于这个结果:我们发现:移位运算符不改变原数值的大小!

00000000000000000000000000000100               4的(原码,反码,补码)

在移位运算符中,移动的是存储在内存中的补码!

 因此,我们可以看出来,左移操作符规则:左边丢弃,右边补0;

当a=-4时候:

 
#include <stdio.h>
int main()
{
	int a = -4;
	//a的原码10000000000000000000000000000100
	int b = a << 1;
	//把a向左移动1位
	printf("a=%d  b=%d\n", a, b);
	return 0;
}

我们需要知道-4的原码,反码,补码

因此:

10000000000000000000000000000100           -4的原码

111111111111111111111111111111111011            -4的反码

111111111111111111111111111111111100             -4的补码

然后在根据刚才序列进行左移一位,得到的结果就是:

111111111111111111111111111111111000               补码

111111111111111111111111111111110111              反码(补码-1)

10000000000000000000000000001000              原码(反码符号位不变,其余位按位取反)

因此该数值为-8

因此,由上面两个代码,我们可以看出:左移操作符有乘2的效果!

注意,补码在移动过程中,如果将符号位移丢了,:那么,移丢就移丢,后面还能补回来!

右移操作符  《

当a=-4时候:

#include <stdio.h>
int main()
{
	int a = -4;
	
	//10000000000000000000000000000100 - 4的原码
 
    //111111111111111111111111111111111011 - 4的反码
 
	//111111111111111111111111111111111100 - 4的补码
	int b = a >> 1;
	//把a向右移动1位
	printf("a=%d  b=%d\n", a, b);
	return 0;
}

下面我们就a=-4来分析右移操作符:

 对于右移操作符:左边空出来的一位:有两种补法!(在C语言中卖淫给出明显的绝对答案,只能根据编译器得来计算答案)

右移操作符:

            a.逻辑右移:

                          右边丢弃,左边补0;

            b.算术右移:(绝大多数是这样的)

                         右边丢弃,左边补原符号位(正数补0,负数补1)

 对于该运算结果,结合二进制的右移结果,我们可以看出来用了算术右移!

因此,我们可以看出来,右移操作符有除2的效果!

3.位操作符(二进制的条件下)

&  按位与

|   按位或

^   按位异或

(1).   &   按位与

下面,笔者来结合此代码来进行分析:

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

00000000000000000000000000000011          3的补码

10000000000000000000000000000101         -5的原码

111111111111111111111111111111111010          -5的反码

111111111111111111111111111111111011          -5的补码

因此,对于:

00000000000000000000000000000011          3的补码

111111111111111111111111111111111011          -5的补码

由&  按位与,可以得出:

00000000000000000000000000000011           补码(原码)

按位与规则:有0则为0,都1则为1

则打印结果为c=3

 (2).      |    按位或

下面,笔者来结合此代码来进行分析(对上面代码进行浅浅改造)

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

还是在补码上进行操作:

00000000000000000000000000000011          3的补码

111111111111111111111111111111111011          -5的补码

对于   |    按位或  ,可以得出:

11111111111111111111111111111111011            补码(负数)

则进补码-1到反码,在到原码的操作,可以得出该数字!

因此: |     按位或规则为:只要有1则为1,两个为0则为0;

最后的打印结果为:

 (3)   ^   按位异或

下面,笔者来结合此代码来进行分析(对上面代码进行浅浅改造)

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

我们仍然需要3跟-5的补码:

00000000000000000000000000000011          3的补码

111111111111111111111111111111111011          -5的补码

由           ^    按位异或得出:

111111111111111111111111111111111000          补码(负数)

则进补码-1到反码,在到原码的操作,可以得出该数字!

因此   ^  按位异或的运算规则为:

相同为0,不同为1;

因此,该代码的运算结果为:

 另外需要注意的是:

^   按位异或:

1,相同的数字按位异或结果为0;即3^3=0;


2,按位异或支持交换律;即3^5^6等于6^3^5;

4.赋值运算符

=

赋值操作符是一个很棒的操作符,它可以让你得到一个你之前不满意的数值,也就是你可以给自己重新赋值

int  weight=120;

weight=89;//不满意就赋值

下面介绍连续赋值

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

 在这里,b=a=a+3;是连续赋值的结果,最后的打印结果为:a=13,b=13;但是不建议这样去写。程序运转错误以后,没有办法去深入该表达式进行调试!

5.赋值运算符

+=            -=          *=          /=                %=           

>>=              <<=           &=          |=          ^=

6.单目操作符

!逻辑反操作符

-  负值

+  正值

&  取地址

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

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

--     前置,后置--

++  前置,后置++

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

(类型)   强制类型转化

1.    ! 逻辑反操作符

笔者将用下面代码来解析:

#include <stdio.h>
int main()
{
	int flag = 0;
	if (!flag)
	{
		printf("hehe\n");
	}
	return 0;
}

在if语句中,用了 !逻辑反操作符,

运转结果为:打印了hehe

 但是笔者前面定义了flag=0,按照if语句中的,0表示假,是不会进入if语句,直接什么都不进行输出!但是最后的运转结果却是输出了hehe ,因此,!  逻辑反操作有取反的意思

2.  &   取地址操作符

&   取地址操作符  常常与      *    间接访问操作符(解引用操作符) 在指针中联用!

int a=10;

int *pa=&a;   //在这里int指a的类型,*指pa为指针变量

#include <stdio.h>
int main()
{
	int a = 10;
	int* pa = &a;
	printf("%d\n", a);
	printf("%d\n", *pa);        //由地址找到该数
	printf("%d\n", pa);            //打印pa的地址
 
	return 0;
}

代码的运转结果为:


 

*pa——》解引用操作符,最后得到a的值10;

pa——》得到a的地址

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

在多处都有涉及!

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

借助此代码,笔者提醒大家,sizeof(表达式)   表达式内部不进行计算!

代码的运行结果为:short类型占2 个字节!在这里s 的值仍然为10;

 注意数组传参时候:

#include <stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));          //8
}
void test2(char ch[])
{
	printf("%d\n", sizeof(ch));             //8
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));              //40
	printf("%d\n", sizeof(ch));           //10
	test1(arr);
	test2(ch);
	return 0;
}
 
 
 
 
 

在这里,我们需要注意的是:数组传参时候,传递的是首元素地址 ,占据4个(32位条件下)或者8个字节(64位条件下)

因此最后的打印结果为:

 之前笔者就这这里栽过,因此需要读者强加注意!

4.数组名

数组名是数组首元素地址

但是有两个列外:

1.sizeof(数组名),在这里数组名表示的是整个数组,不是首元素地址

sizeof(数组名)计算的是整个数组的大小,单位是字节

2.   &数组名,在这里数组名表示的是整个数组,不是首元素地址,

&数组名,取出的是整数组的地址!

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

下面笔者将用代码来进行讲解:

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

在这楼里,我们仍然需要最大a=0的二进制

00000000000000000000000000000000       0的补码

~      对一个数的二进制进行按位取反(包过符号位)

11111111111111111111111111111111           补码(负数)

11111111111111111111111111111110         反码(补码-1)

1000000000000000000000000001            原码(反码符号位不变,其余位按位取反)

即得到的结果为-1;

 7,逻辑操作符

&&   逻辑与操作符

||      逻辑或操作符

下面笔者将用代码来进行讲解:

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

在该段代码中,用了前后置++运算符,因此我们需要注意:++i;先++,后输出,i++,先使用,后++;

&&   逻辑与操作符     只要前面有0,就不进行后面的运算

||      逻辑或操作符      只要前面有1,后面也就不用计算

 对于a++先使用后++,因此,a=0,然后在进行后面.........;但是:&&   逻辑与操作符     只要前面有0,就不进行后面的运算,因此,后面的b,c,d,都不进行运算,然后a在++,然后输出a=1;

8.条件操作符(唯一一个三目运算符)

exp1?exp2:exp3

a>5?3:8

exp1用来判断条件是否成立,成立则用exp2,否则用exp3

9.逗号表达式

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

逗号表达式从左到右依次执行(将前面的结果赋值给后面的字母相同的表达式),表达式的结果为最后一共表达式的结果;

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

在int c = (a > b, a = b + 10, a, b = a + 1);,我们可以看出来最后c的结果等于最后一个表达式b=a+1的结果!从前面依次计算表达式,可以得出a=12,b=13

运算结果为:

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。