文章目录
一、操作符的含义
操作符(Operator) 是一种告诉编译器执行特定的数学或逻辑操作的符号。操作符又称为运算符,作为运算对象的变量或者常量称为操作数。操作符左侧的操作数称为第一操作数或者左操作数,操作符右边的操作数称为第二操作数或者右操作数。操作符同时对两个操作数进行运算的称为双目操作符,操作符只对一个操作数进行运算的称为单目操作符。
二、操作符的分类
● 算术操作符:+、-、*、/、%
● 移位操作符:<<、>>
● 位操作符: &、|、^
● 赋值操作符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=
● 单目操作符:!、++、- -、&、*、+、-、~、sizeof、(类型)
● 关系操作符:>、>=、<、<=、==、!=
● 逻辑操作符:&&、||
● 条件操作符:? :
● 逗号表达式:,
● 下标引用操作符:[ ]
● 函数调用操作符:( )
● 结构成员访问操作符:. 、->
三、运算符功能介绍
1.算术操作符
(1) +(加法运算符):实现两个操作数的加法运算,是一个双目操作符。例如:
int a = 2;
int b = 3;
int c = a+b;//实现两个整型变量的加法运算
printf("%d\n",c); //结果为5
printf("%d\n",a+6);//变量和常量相加,结果为8
printf("%d\n",3+4);//常量和常量相加,结果为7
当+只有一个右操作数的时候,就是正号,它就是一个单目操作符。
int n = +10;
printf("%d\n",n); //结果为10
同样的 -(减法操作符):实现两个操作数的减法运算。当 - 只有一个右操作数的时候,它就是负号,就是一个单目操作符。
(2) *(乘法操作符):实现两个操作数的乘法运算。键盘上通过shift+8键敲出来。*是一个双目操作符。
int a = 3;
int b = 7;
printf("%d\n",a*b);//结果为21
/(除法操作符):实现两个操作数的除法运算。是一个双目操作符。
printf("%d\n",10/5);//打印结果为2
printf("%d\n",5/2);//打印结果为2
printf("%lf\n",3.0/2);//打印结果为1.500000
printf("%lf\n",3.0/2.0);//打印结果为1.500000
注意在做两个操作数的除法运算时:
当/(除号)两边都是整型类型的操作数时,则得到的结果只会是整型。比如上面的第二行5/2的结果本应该是2.5,但是只会保留整数部分的2,而舍弃小数部分。所以以%d的形式打印出的结果就为2。
当/(除号)两边至少有一个是浮点数类型的操作数时,则就会计算出小数的结果。比如上面的3.0/2、3.0/2.0得到的结果就都是1.5,以%lf的形式打印,会在屏幕上打印出1.500000,(注意以%lf的形式打印,小数点后默认会打印出6位。)
(3)%(取余(模)操作符):用于求两个整型相除以后的余数,是一个双目操作符。%运算符要求两个操作数必须是整数,得到的余数肯定也是整数。
printf("%d\n",7%2);//打印结果为1
printf("%d\n",14%3);//打印结果为2
printf("%d\n",3%5);//打印结果为3
注意:当被除数小于除数时,得到的余数就是被除数。
2.关系操作符
关系操作符都是双目操作符。特别多的会用在循环条件的部分,if语句中。
int age = 10;
if(age>=18)
printf("成年了\n");
else
printf("未成年\n");
运行结果:
char ch[10]="abcdefg";
int i = 0;
while(ch[i]!='\0')
{
printf("%c ",ch[i]);
i=i+1;
}
运行结果:
上面只举了两个例子,其实对于关系运算操作符很简单。这里只是做简单的介绍:>(大于)、>=(大于等于)、<(小于)、<=(小于等于)、==(等于)、!=(不等于)。(注意:在判断是否是等于关系时,两个等号==才是判断相等,而一个等号=是赋值。不要混淆)
对于关系运算的结果只有0和1两种结果,0表示假,1表示真。
printf("%d\n",3>2);//打印结果是1
printf("%d\n",3!=3);//打印结果是0
在C语言中非0表示真,0表示假。
3.逻辑操作符
(1)&&:逻辑与操作符,双目操作符。顾名思义就是"并且"的意思,形式是:a && b,a和b可以是常量、变量或者表达式。当&&两边的a和b至少有一个为假时,整个表达式的结果就为假;当&&两边的a和b都为真时,整个表达式的结果才为真:
printf("%d\n",(3 >= 2) && (7 < 9));//打印结果为1
printf("%d\n", (3 <= 2) && (3 != 2));//打印结果为0
printf("%d\n", (4 < 2) && (5 >= 8));//打印结果为0
(2)||:逻辑或操作符,双目操作符。逻辑或就是"或者"的意思。形式为:a || b,a和b可以是常量、变量或者表达式。当||两边的a和b至少有一个为真时,整个表达式的结果就为真;当||两边的a和b都为假时,整个表达式的结果才为假:
printf("%d\n", (3 >= 2) || (7 < 9));//打印结果为1
printf("%d\n", (7 >= 6) || (4 != 4));//打印结果为1
printf("%d\n", (4 < 2) || (5 >= 8));//打印结果为0
逻辑操作符的短路现象
(1)逻辑与短路:对于表达式a && b,当&&左边的a已经是假了,那右边的b就不会判断了。因为左边的a已经为假了,则整个表达式就为假。
(2)逻辑或短路:逻辑或短路也是相似的,对于表达式a || b,当||左边的a已经是真了,那右边的b就不会判断了。因为左边的a已经为真,则整个表达式就为真。
对于逻辑操作符的短路现象,就是仅仅根据左操作数的结果就能知道整个表达式的结果,而不再对右操作数进行计算,这就是短路现象。
4.(复合)赋值操作符
(1)=(赋值操作符):赋值运算是将赋值号右边的值赋给左边的变量。赋值号右边的值可以是常量、变量或者表达式,而赋值号左边必须是一个变量。
(2)复合赋值运算符:+=(加等于)、-=(减等于)、*=(乘等于)、/=(除等于)、%=(模等于)
+=(加等于):把右边操作数加上左边操作数的结果赋给左边操作数。举一个例子就明白了:
int a = 5;
a += 3;//等价于a=a+3
printf("%d\n",a);//打印结果为8
定义了一个整型变量a,并初始化其值为5。a+=3的意思就是a=a+3,将变量a的值加上常量3后的结果赋给变量a,则a的值变为了8。复合赋值操作符其实就是算术运算符结合赋值运算符的一种简化。上面的其他复合赋值操作符也是相应的算术运算符结合赋值操作符的意思。赋值操作符及复合赋值操作符都是双目操作符,因为他们都有两个操作数。
5.单目操作符
(1)!(非):逻辑反操作符。通俗来说,就是将真变为假,假变为真。
printf("%d\n",3>2);//打印结果为1
printf("%d\n",!(3>2));//打印结果为0
(2)++操作符:也叫自增运算符,分为前置++和后置++。
①前置++:
#include <stdio.h>
int main()
{
int a = 1;
int b = ++a;
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
运行结果:
由上面的代码及结果可知,前置++的作用是,先将变量的值加1以后,再使用变量的值。就像上面的例子,++a可以理解为先让变量a自增1(a=a+1),然后再使用a的值,此时a的值为2(先加1,后使用)。你也可以理解为++a这个表达式的值就为2,当执行完++a这个表达式后,会使a的值自增1:
#include <stdio.h>
int main()
{
int a = 1;
printf("++a = %d\n", ++a);
printf("a = %d\n", a);
return 0;
}
运算结果:
②后置++:
#include <stdio.h>
int main()
{
int a = 1;
printf("a++ = %d\n", a++);
printf("a = %d\n", a);
return 0;
}
运行结果:
后置++的意思就是先使用变量的值,然后再让变量的值自增1(先使用,后加1)。就像上面的代码,a++是先使用a的值,a的值为1,所以a++这个表达式的值为1。当a++这个表达式执行完毕后,会让a的值自增1(a=a+1)。你可以理解为a++这个表达式的值就为原来a的值,执行完这条语句后,a的值自增1。
(3)- -操作符:也叫自减操作符,也是分为前置- -和后置- -。用法和意思和前面的++操作符类似:
#include <stdio.h>
int main()
{
int n = 4;
//前置--
printf("--n = %d\n", --n);//先让n自减1,然后再使用n的值
printf("n = %d\n", n);
//后置--
printf("n-- = %d\n", n--);//先使用n的值,然后让n自减1
printf("n = %d\n", n);
return 0;
}
运行结果:
注意:无论是前置++、- -或是后置++、- -,到表达式执行完毕后,都会使变量的值自增1或者自减1。
(4)&:取地址操作符,顾名思义就是取出变量的地址。
#include <stdio.h>
int main()
{
int n = 1;
&n;//取出变量n的地址
int* p = &n;//将变量n的地址存到指针变量中
return 0;
}
(5)*:解引用操作符,用于指针(地址),获取指针所指向单元的内容。用法如下:
#include <stdio.h>
int main()
{
int a = 10;
int* p = &a;
*p = 20;
printf("a = %d\n", a);//打印结果为20
return 0;
}
有了*操作符,就多了一种修改变量值的途径。可以通过解引用操作符,对指针进行解引用,间接的访问指针所指向对象的内容。
(6)sizeof操作符:用于求一个变量或者类型所占空间的大小,单位是字节。
#include <stdio.h>
int main()
{
int b = 10;
printf("%d\n", sizeof(b));
printf("%d\n", sizeof b);
printf("%d\n", sizeof(int));
return 0;
}
sizeof操作符求变量的大小时,后面的( )可以省略。还需要注意的是,sizeof操作符中放的如果是表达式,则表达式是不会计算的,但是会判断表达式最终结果的数据类型,由此求出最终结果的大小(单位字节)。
#include <stdio.h>
int main()
{
int a = 10;
char b = '\0';
printf("%d\n", sizeof(a+10));
printf("%d\n", sizeof(b = 'a' + 'b'));
return 0;
}
运行结果:
(7)(类型):强制类型转换。作用就是将表达式的类型转换为类型名指定的数据类型。
#include <stdio.h>
int main()
{
int a = 10;
float b = 3.14f;
a = (int)b;//将浮点型的b强制类型转换成整型赋给a
printf("a = %d\n", a);//打印结果为3
return 0;
}
上面的变量a是一个整型,而变量b是一个浮点型数据,如果直接将b的值赋给a,则类型就不兼容。所以将b强制类型转换成整型(去掉小数点后的值,保留整数部分),再赋给a。用法是在变量或者表达式的前面加上一个( ),( )内注明要转换的类型。强制类型转换是将所需变量或者表达式的值转换为我们需要的类型,不会改变原来变量和表达式的属性类型。在后面的学习中会遇到更多强制类型转换的代码,这里先做一个大概的了解。
6.条件操作符
?:(条件操作符)。条件操作符是C语言中唯一的一个三目操作符,意思就是他有三个操作数。
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
printf("请输入a和b的值:");
scanf("%d %d", &a, &b);
int c = a > b ? a : b;
printf("%d\n", c);
return 0;
}
运行结果:
条件操作符的格式:表达式1 ?表达式2 : 表达式3
①当表达式1的结果为真(非0)时,则计算表达式2,表达式2的结果就为整个表达式的结果。
②当表达式1的结果为假(0)时,那么就计算表达式3,表达式3的结果就为整个表达式的结果。上面的3个表达式可以是变量、常量或者表达式:
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
printf("请输入a和b的值:");
scanf("%d %d", &a, &b);
int c = a > b ? a-2 : b+3;
printf("%d\n", c);
return 0;
}
运行结果:
7.逗号表达式
表达式1,表达式2,表达式3,… :逗号表达式,也是一个操作符。用 , 将各个表达式分隔开(英文半角状态下的逗号)。运算法则是按从左往右的顺序计算各个表达式。
#include <stdio.h>
int main()
{
int x = 7;
int y = 9;
int m = 12;
int n = 1;
int a = (x = y + 1, y = m++, m = ++n, n = x + y + m);
printf("x = %d y = %d m = %d n = %d a = %d",x,y,m,n,a);
return 0;
}
运行结果:
通过上面的代码及运行结果,第八行的代码,因为( )的优先级高于赋值操作符(=),所以会先计算( )里面的逗号表达式,因为逗号表达式是左结合性,所以会从左往右顺序计算各个表达式,最后一个表达式的结果就是整个表达式的结果。注意上面第八行的逗号表达式是用( )整体括起来的,然后再赋值给变量a。如果没有打( ),就是另外一种情况:
#include <stdio.h>
int main()
{
int x = 7;
int y = 9;
int m = 12;
int n = 1;
int a = 0;
a = x + y, y = m++, m = ++n, n = x + y + m;
printf("x = %d y = %d m = %d n = %d a = %d",x,y,m,n,a);
return 0;
}
运行结果:
上面第九行的代码,也是逗号表达式,只是这里没有对逗号表达式整体打括号,因为逗号表达式是C语言中优先级最低的运算符,所以相比较于逗号表达式,赋值操作符的优先级高,就会将x+y计算后的值赋值给a,而不是将最后一个表达式的结果赋给a。
除非像上面一样逗号表达式整体加了括号以后(a=(x+y,y=m++,m=++n,n=x+y+m))才会将最后一个表达式的结果赋给a。
这里虽然没有整体打括号,但由于逗号表达式的左结合性,上面第九行的逗号表达式会从左往右依次计算各个表达式。通过上面的输出结果就可以看出来了。
8.下标引用操作符
[ ]:下标引用操作符。是在数组中使用的,是一个双目操作符,用于访问数组中的元素。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
下标引用操作符也是一个双目操作符,[ ]左边的数组名和[ ]中的下标就是它的操作数。其实两个操作数的位置是可以交换的,也就是数组名放在[ ]中,下标放在[ ]的左边这种也是可以的。
9.函数调用操作符
( ):函数调用操作符,在调用函数时,函数名后面的( )就是函数调用操作符。( )的操作数是:函数名、参数。而且函数调用操作符最少有一个操作数,那就是函数名,因为有的函数是没有参数的。
#include <stdio.h>
int Add(int x, int y)
{
return x + y;
}
void test()
{
printf("I am xionger!");
}
int main()
{
int x = 10;
int y = 20;
printf("%d\n",Add(x, y));//这里的()就是函数调用操作符
test(); //这里的()就是函数调用操作符
return 0;
}
10.结构成员访问操作符
(1) 结构体成员的直接访问,就可以使用 . 操作符。使用方法是:结构体变量.成员名。
#include <stdio.h>
struct Stu
{
char name[20];
char sex[12];
int age;
char id[10];
};
int main()
{
struct Stu s1 = { "张三","男",20,"202400101"};
printf("%s %s %d %s\n", s1.name, s1.sex, s1.age, s1.id);//直接访问
return 0;
}
运行结果:
(2)结构体成员的间接访问,可以使用->操作符,通过结构体指针来实现对结构体成员的间接访问。
#include <stdio.h>
struct Stu
{
char name[20];
char sex[12];
int age;
char id[10];
};
int main()
{
struct Stu s1 = { "张三","男",20,"202400101"};
struct Stu* p = &s1;
printf("%d %s %s %s\n", p->age, p->sex, p->name, p->id);//间接访问
return 0;
}
运行结果:
上面只是初步了解,这些操作符的意思和使用方法,在后期的学习中还会更深入的接触和学习到上面的众多操作符。上面还有关于位的众多操作符和运算符的优先级还没有学习,我们放到下一章节学习。