C语言操作符详解——看完直接懂(覆盖所有操作符,每个操作符都有示例)
一、操作符分类
• 算术操作符: + 、- 、* 、/ 、% • 移位操作符: << >> • 位操作符: & | ^ ~ • 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^= • 单目操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型) • 关系操作符: > 、>= 、< 、<= 、 == 、 != • 逻辑操作符: && 、|| • 条件操作符: ? : • 逗号表达式: , • 下标引用: [] • 函数调用: () • 结构成员访问: . 、->二、算术操作符
算术操作符为:+ - * / %这几种,用来进行简单的运算,因为这些操作符的操作数都有两位,所以这种操作符也叫双目操作符
2.1+ - * /
操作符+ - * /用来进行加法、减法、乘法、除法的运算
比如:
#include<stdio.h>intmain(){inta=5;intb=2;printf("%d\n",a+b);//7printf("%d\n",a-b);//3printf("%d\n",a*b);//10printf("%d\n",a/b);//2return0;}/操作符:
- 两个操作数都是整型,进行的是整数除法,得到的结果为整数(舍去数学中除法后面的小数)
- 两个操作符中至少有一个浮点数,进行的就是浮点数除法,得到的结果为浮点数
比如:
#include<stdio.h>intmain(){inta=5;intb=2;doublec=2.0;printf("%d\n",a/b);//2printf("%lf\n",a/c);//2.500000return0;}2.2%
%表示求模运算,即返回两个整数相除的余数。两端的操作符只能是整数,不能是浮点数。
比如:
#include<stdio.h>intmain(){inta=5;intb=2;intc=3;printf("%d\n",a%b);//1printf("%d\n",a%c);//2return0;}负数求模:结果的正负号由第一个运算数的正负号决定
比如:
#include<stdio.h>intmain(){inta=5;intb=-2;printf("%d\n",a%b);//1printf("%d\n",b%a);//-2return0;}三、移位操作符
在C/C++语言中移位操作符的操作数必须是整数类型,不能是浮点数。
对于整数来说,数据是用的补码存放到内存中的,所以移位操作符其实是对整数在内存中存储的补码进行操作的,所以在学习位移操作符之前我们得先了解整数在内存中存储的各种形式。
3.1 原码、反码、补码
整数的2进制表示方法有三种,即原码、反码和补码
有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号 位,剩余的都是数值位。
符号位都是用0表示“正”,用1表示“负”。
最高位是最左边的,由左至右递减
正整数:正整数的原、反、补码都相同。
负整数:负整数的三种表示方法各不相同。
- 原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
- 反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
- 补码:反码+1就得到补码。
- 补码得到原码也是可以使用:取反,+1的操作。
比如:
int a = 5; 00000000 00000000 00000000 00000101 - 原、反、补码 最高位(最左边的)为符号位,因为是正数,所以符号位为0 int b = -2; 10000000 00000000 00000000 00000010 - 原码,因为是浮点数,所以符号位为1 11111111 11111111 11111111 11111101 - 反码,原码的符号位不变,其他位依次按位取反 11111111 11111111 11111111 11111110 - 补码,反码+1整数在内存中存储的时候使用的是补码,CPU在计算机的计算的时候也是用的补码,但是打印出来的或者人使用的时候用的是原码
3.2 左移操作符 <<
移位规则:左边抛弃、右边补0(移的是补码)
比如:
#include<stdio.h>intmain(){inta=5;//补码:00000000 00000000 00000000 00000101printf("%d\n",a<<1);//10//左移一位:00000000 00000000 00000000 000001010 - 补码(10)intb=-2;//原码:10000000 00000000 00000000 00000010//补码:11111111 11111111 11111111 11111110printf("%d\n",b<<1);//-4//左移一位:11111111 11111111 11111111 11111100 - 补码//10000000 00000000 00000000 00000100 - 原码(-4)return0;}3.3 右移操作符 >>
移位规则:首先右移运算分两种:
- 逻辑右移:左边用0填充,右边丢弃
- 算术右移:左边用原该值的符号位填充,右边丢弃(大部分的编译器用的都是算术右移,后面的举例也采用的算术右移的方式)
比如:
#include<stdio.h>intmain(){inta=10;//补码:00000000 00000000 00000000 000001010printf("%d\n",a>>1);//5//右移一位:00000000 00000000 00000000 00000101 - 补码(5)intb=-4;//原码:10000000 00000000 00000000 00000100//补码:11111111 11111111 11111111 11111100printf("%d\n",b>>1);//-2//右移一位:11111111 11111111 11111111 11111110 - 补码//10000000 00000000 00000000 00000010 - 原码(-2)return0;}警告⚠️:对于移位运算符,不要移动负数位,这个是标准未定义的。
int c = 52; c >> -1;//error四、位操作符
位操作符有:
& //按位与 | //按位或 ^ //按位异或 ~ //按位取反 这是个单目操作符 注:它们的操作数必须是整数,而且是使用整数在内存中存储的补码形式来进行位操作的。操作方式:
&:每个对应的bit位,都为1则该位结果为1,否则为0 |:每个对应的bit位,有1则该位结果为1,都为0结果才为0 ^:每个对应的bit位,相异则该位结果为1,相同则为0 ~:把每一个bit位取反比如:
#include<stdio.h>intmain(){inta=5;//5的补码:00000000 00000000 00000000 00000101intb=-2;//-2的补码:11111111 11111111 11111111 11111110printf("%d\n",a&b);//4//00000000 00000000 00000000 00000101//11111111 11111111 11111111 11111110//00000000 00000000 00000000 00000100 - 4printf("%d\n",a|b);//-1//00000000 00000000 00000000 00000101//11111111 11111111 11111111 11111110//11111111 11111111 11111111 11111111 - -1printf("%d\n",a^b);//-5//00000000 00000000 00000000 00000101//11111111 11111111 11111111 11111110//11111111 11111111 11111111 11111011 - -5printf("%d\n",~a);//-6//00000000 00000000 00000000 00000101//11111111 11111111 11111111 11111010 - -6return0;}五、赋值操作符
赋值操作符: • = += -= *= /= • <<= >>= &= |= ^=改变一个变量的操作叫做赋值
比如:
#include<stdio.h>intmain(){inta=5;//初始化a=2;//赋值printf("%d\n",a);return0;}5.1 复合赋值符
符合赋值符: • += -= *= /= %= • >>= <<= • &= |= ^= 比如:a += 2等同于a = a + 2其它的符合赋值符用法跟这个类似比如:
#include<stdio.h>intmain(){inta=5;printf("%d\n",a+=2);//7intb=2;printf("%d\n",b-=5);//-3intc=6;printf("%d\n",c*=2);//12return0;}六、单目操作符
单目操作符: • !: 逻辑取反操作符 • ~ :按位取反操作符 • ++ :自增操作符 • -- :自减操作符 • + :正号操作符 • - :负号操作符 • & :取地址操作符 • * :解引⽤操作符 • sizeof :长度计算操作符 • (类型) :强制类型转换操作符 ———————————————— 版权声明:本文为CSDN博主「梓䈑」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/2302_76713442/article/details/1407552806.1++和–
++和--是自增和自减操作符,分为前置和后置
前置和后置的区别:
前置:先+1后使用 后置:先使用后+1比如:
#include<stdio.h>intmain(){inta=5;intb=++a;//a先+1再将+1后的值赋给bprintf("a = %d b = %d\n",a,b);//a = 6 b = 6intn=2;intm=n++;//n先将值赋给m再+1printf("n = %d m = %d\n",n,m);//n = 3 m = 2return0;}--可是同理:
#include<stdio.h>intmain(){inta=5;intb=--a;printf("a = %d b = %d\n",a,b);//a = 4 b = 4intn=2;intm=n--;printf("n = %d m = %d\n",n,m);//n = 1 m = 2return0;}6.2+ -
这里的+ -表示正号和负号
#include<stdio.h>intmain(){inta=+5;intb=2;printf("a = %d b = %d\n",a,-b);//a = 5 b = -2return0;}6.3& *
&:取地址操作符 *:解引用操作符比如:
#include<stdio.h>intmain(){inta=10;int*p=&a;// & 取地址printf("%d\n",*p);// * 解引用,输出 10*p=20;// 通过指针修改 aprintf("%d\n",a);// 输出 20return0;}6.4sizeof
sizeof是专门计算数据类型长度的操作符,sizeof的计算结果是size_t类型的
用法:
#include<stdio.h>intmain(){inta=5;doubleb=2.0;printf("%zd\n",sizeofa);//4printf("%zd\n",sizeofb);//8printf("%zd\n",sizeof(char));//1printf("%zd\n",sizeof(float));//4return0;}6.5 强制类型转换操作符
(类型):强制类型转换操作符 用法: int a = 5.2;////a是int类型, 5.2是double类型,两边的类型不⼀样,编译器会发出警告 为了消除这个警告我们可以用强制类型转换操作符来解决 int a = (int)5.2;//将5.2强制类型转换为int类型七、关系操作符
关系操作符: > 、>= 、< 、<= 、 == 、 != 关系操作符其实是对表达式进行判断是否为真,返回值为1(真)或0(假)比如:
#include<stdio.h>intmain(){inta=5;intb=2;printf("%d\n",a>=b);//1printf("%d\n",a<=b);//0printf("%d\n",a==b);//0printf("%d\n",a!=b);//1return0;}八、逻辑操作符
逻辑操作符: • !:逻辑取反操作符(改变单个表达式的真假)。 • && :逻辑与操作符,两侧的表达式都为真,则为真,否则为假,就是并且的意思。 • || :逻辑或操作符,两侧只要有⼀个表达式为真,就为真,两侧的表达式都为假结果才为假,就是或者的意思。 逻辑操作符的返回值为:1(真)或者0(假)比如:
#include<stdio.h>intmain(){inta=5;intb=2;intc=0;printf("%d\n",!c);//1printf("%d\n",!a);//0printf("%d\n",a&&b);//1printf("%d\n",a&&c);//0printf("%d\n",a||b);//1printf("%d\n",a||c);//1return0;}九、条件操作符
条件操作符: 表达式 ? 结果1 : 结果2; 条件操作符的运算逻辑: 如果表达式为真返回结果1,表达式为假返回结果2比如:
#include<stdio.h>intmain(){inta=5;intb=2;intc=(a<b)?a:b;//表达式(a < b)为假,返回bprintf("%d\n",c);//2return0;}十、逗号表达式
逗号表达式: 表达式1, 表达式2, 表达式3, ..., 表达式n 逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。比如:
#include<stdio.h>intmain(){inta=5;intb=2;intc=(a>b,a=b+10,a,b=a+1);//从左至右执行,c为最后一个表达式(b = a + 1)的结果printf("%d\n",c);//13return0;}十一、下标访问操作符
操作数:一个数组名 + 一个索引值(下标)比如:
#include<stdio.h>intmain(){intarr[520]={0,1,2,3,4,5};inta=arr[2];printf("%d\n",a);//2return0;}十二、函数调用操作符
函数调用操作符: 接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。比如:
#include<stdio.h>intAdd(inta,intb){returna+b;}intmain(){inta=5;intb=2;intret=Add(a,b);//这里的()就是函数调用操作符,它的操作数是Add、a、bprintf("%d\n",ret);//7return0;}十三、结构成员访问
13.1 结构体
C语言已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类 型还是不够的,假设我想描述学生,描述一本书,这时单一的内置类型是不行的。
描述一个学生需要名字、年龄、学号、身高、体重等; 描述一本书需要作者、出版社、定价等。
C语言为了解决这个问题,增加了结构体这种自定义的数据类 型,让程序员可以自己创造适合的类型。
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如: 标量、数组、指针,甚至是其他结构体。
结构体的声明:
结构体的声明: struct tag { member-list; }variable-list;//这个分号要有比如:
structStu//创建结构体类型struct Stu{charname[20];intage;intid;}a={"linlin",18,2025005};//在创建结构体类型struct Stu的同时创建结构体变量A(全局变量)并初始化intmain(){structStub={"lisi",16,2025002};//创建结构体变量B并初始化return0;}13.2->
结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数。
比如:
#include<stdio.h>structStu//创建结构体类型struct Stu{charname[20];intage;intid;}a={"linlin",18,2025005};//在创建结构体类型struct Stu的同时创建结构体变量A(全局变量)并初始化intmain(){structStub={"00_linlin",18,2025002};//创建结构体变量B并初始化printf("%s %d %d\n",a.name,a.id,a.age);//通过点操作符(.)来访问printf("%s %d %d\n",b.name,b.id,b.age);return0;}