C语言——操作符详解

目录

1、算术操作符

2、位操作符

算术右移:

 3.赋值操作符 

 4.复合赋值符

5.单目操作符

6.关系操作符

7.逻辑操作符

8.条件操作符

 9.逗号表达式

 10.下标引用、函数调用和结构成员



1、算术操作符

 +        -        *        /        %

       %  是取模操作符,意思就是 求余数。


	int ret = 10 % 3;   //求10 % 3的余数,得出的余数是1

	printf("%d\n", ret);

      注意的是:% 操作符不能用于浮点数,只能作用于整数,如果作用于浮点数将会报错。

      对于 /(除法)操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。什么意思呢?请看下面的代码


	int ret = 10 / 3;     //   / 两边的操作都是整数,执行的就是整数除法,结果为3  

	printf("%d\n", ret);

       如果 / 两边的操作数有一个数为浮点数的话,执行的是浮点数除法

double ret = 10 /3.0;        //   得出的结果是 3.333333
printf("%lf\n", ret);

2、位操作符

<<          左移操作符

>>          右移操作符

注:移位操作符的操作数只能是整数,不能是浮点数。

讲之前先了解一下原码、反码、补码是什么? 一个正整数的原,反,补码都是一样的,负整数则不同,需要计算。

C语言——操作符详解_第1张图片

 为什么要讲这些呢,因为一个整数在内存中存储的是补码!!!

接下来回归主题:

        <<         左移操作符规则:左边抛弃,右边补0

C语言——操作符详解_第2张图片

如果a是负数的呢?

C语言——操作符详解_第3张图片

         >>          右移操作符可以分为:

                        1、算术右移    (右边丢弃,左边补原来的符号位数)

                        2、逻辑右移    (右边丢弃,左边不用考虑符号位数,直接用0补充)

        到底是 算术右移还是 逻辑右移,取决于编译器

        我们常见的编译器大多都是算术右移

算术右移:

C语言——操作符详解_第4张图片

int a= 5;
int b= a>> -2;    //标准未定义的

对于移位运算符还需要注意的一点是:不要移动负位数,这是标准未定义的,什么意思呢,就是c语言并没有规定负移位数该怎么做,所以不能写成负数

 3、位操作符:

        &      按(二进制)位 与

         |       按(二进制)位 或

         ^       按(二进制)位 异或  

& 按位与: 两个条件同时为真(1)的情况下,运算结果为真,说人话就是两个条件都是1才为1,否则为0

C语言——操作符详解_第5张图片

 |  按位或 :任意一个条件为真(1)的情况下,运算结果为1,就是只要有一个1则为1,否则为0。

C语言——操作符详解_第6张图片

 ^ 按位异或 :两个条件中只有一个条件为真(1)的情况下,运算结果为真。也就是说,相异才为 真,相同则为假。

C语言——操作符详解_第7张图片

 这里有道关于异或的题目:不能创建临时变量(第三个变量),实现两个数的交换。

了解之前要先知道:两个相同的数进行异或的话为0; 0跟其他数进行异或都是这个数的本身。

C语言——操作符详解_第8张图片

#include

int main()
{
	int a = 5;
	int b = 3;
	printf("交换前:a=%d  b=%d\n", a, b);
	a = a ^ b;
	b = a ^ b;	//相当于 a^( b ^ b),所以b等于5
	a = a ^ b;	//相当于 a^ b,等于3
	printf("交换后:a=%d  b=%d\n", a, b);

	return 0;
}

结果  :

C语言——操作符详解_第9张图片

C语言——操作符详解_第10张图片

 3.赋值操作符 

=

这个没什么好讲的,相信大家都会。

nt weight = 120;  // 体重
weight = 89;        //  不满意就重新赋值
double salary = 10000.0;
salary = 20000.0;        //使用赋值操作符赋值


赋值操作符可以连续使用,比如:
int a = 10;
int x = 0;
int y = 20;
a = x = y+1;        //连续赋值
这样的代码看着感觉如何?是不是没那么容易一眼看懂了,这种写法是不推荐的。
换个写法,你看看:
 x = y+1;
 a = x;
这样的写法是不是更加易懂了

 4.复合赋值符

+=

-=

*=

/=

%=

>>=

<<=

&=

|=

^=

这可是懒人的福音了,怎么说呢?

int x= 10;
x= x + 10;

x+=10;  // 可以写成这样,等价于x= x + 10;

//其他的运算符也是一样的操作

5.单目操作符

!                        逻辑反操作符

-                          负值

+                         正值

&                        取地址

sizeof                 查询对象或类型的大小

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

--                        前置、后置减减

++                      前置、后置加加

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

(类型)                强制类型转换

!  逻辑反操作符是什么呢?下面代码演示:

	int flag = 0;
	//当flag为假的时候如何打印haha?
	if (!flag)	//只需用上逻辑反操作符 ! 就能打印了
	{
		printf("haha\n");
	}

逻辑反操作符就是把 真变成假,假变成真。把flag变成真,不会是别的数字,只会是1。

sizeof  是一个关键字,可以用来求一个变量或类型所占内存空间的大小(单位:字节)

	int a = 10;
	printf("%d\n", sizeof(a));   //计算a所占内存空间的大小为4个字节
	printf("%d\n", sizeof(int)); //计算int类型为4个字节

	int arr[5] = { 1,2,3,4,5};
	printf("%d\n", sizeof(arr));  // 数组名 arr 单独放在sizeof代表的是整个数组,
								  //因为arr数组是int型且里面有5个元素,
                                  //int型大小是4个字节,所以总大小为20个字节

关于sizeof    有些写法会比较怪


	int a = 6;
	printf("%d\n", sizeof a);  //这种写法没有问题,以此证明sizeof不是库函数而是一个关键字,
							   //括号可以省略,如果sizeof是库函数的话括号是不能省略的
								

~ :按(内存中补码的2进制)位取反

int a=0;

printf("%d\n",~a);

//  0000 0000 0000 0000 0000 0000 0000 0000  -因为0是正数,原反补相同
//  1111 1111 1111 1111 1111 1111 1111 1111  - 把0的补码每一位进行取反

//又因为要打印出来,得把补码转换成原码
//  1111 1111 1111 1111 1111 1111 1111 1111  - 补码
//  1111 1111 1111 1111 1111 1111 1111 1110  - 反码
//  1000 0000 0000 0000 0000 0000 0000 0001  - 原码

//  打印出来的结果为 -1

--         前置、后置减减

++       前置、后置加加

int a=9;
int b= ++a;  // 前置++ :先++,再使用,意思就是:a先++,然后再赋值给b

printf("a=%d  b=%d\n",a,b);   // a的结果为10 , b的结果也为10


//如果换种写法呢?

int a=9;
int b= a++;   //后置++ :先使用,再++。意思就是:先把a赋值给b,然后a再++

printf("a=%d  b=%d\n",a,b);   //  因此结果就跟上面的不一样了。 a的结果为10,b则为9 

相信大家遇到过这种题

C语言——操作符详解_第11张图片

这种写法其实是非常有问题的,不同 的编译器结果是不一样的。

vs2019的结果为:4,12。           gcc: 4,10。大家要避免写出这样的代码。

* 解引用操作符

int a=10;
int *p=&a;

*p=20;  // p是指针变量存的是a的地址,*p 解引用操作符通过p存放的地址找到a,并重新给a赋值成20;

printf("%d\n",a);   // 因此a最终的结果为20

 (类型)              强制类型转换

int a=3.14    // 3.14是double型,如果要把3.14强制放到int型的a里面的话会有警告。

//换种写法

int a= (int)3.14;  把3.14强制转换成int型

printf("%d\n",a);   //a的结果为3。

6.关系操作符

>
>=
<
<=
!=         用于测试“不相等”
==        用于测试“相等”

这些关系运算符比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。

int a = 10;
	// a如果等于10 的话打印 您好  ,不等于10的打印  再见
	if (a == 10)
	{
		printf("您好\n");
	}
	else
	{
		printf("再见\n");
	}

	//有些人会把 == 误打成 =  如果写成这样,是把10赋值给a,a是真,就会直接打印成您好
	if (a = 10)
	{
		printf("您好\n");
	}
	else
	{
		printf("再见\n");
	}

7.逻辑操作符

&&                逻辑与(可以理解成:并且、与的意思)

 ||                  逻辑或(可以理解成:或 的意思)

这两个操作符是用于表示逻辑上的真假。到底是什么东西呢?

	//如果要想表示输入的年龄 0到18 之间打印未成年,如何表示呢? 0 < age < 18 ?
	int age = 0;
	scanf("%d", &age);
	if (0 < age < 18)
	{
		printf("未成年\n");
	}
	
	//这种写法是错误的,假设输入的年龄是23,0小于23,结果为真则 1,1小于18,就会打印出未成年了
    //23岁了不应该是成年了吗?怎么打印出的结果会是未成年呢,所以这样的写法是错误的

C语言——操作符详解_第12张图片

 到底要该如何表示呢?这时候逻辑与操作符就派上用场了。

    int age = 0;
    scanf("%d", &age);
	if (age> 0  && age <18)  //可以这样理解:age > 0 并且 age <18 两个条件同时为真才会打印未成                
    {                        //年,其中只要有一个条件不为真就不会执行该语句
	
		printf("未成年\n");
	}

那如果要检测输入的数值是不是1到7的范围呢?可以使用逻辑或操作符。

	int num = 0;
	scanf("%d", &num);
	if (num < 0 || num > 7)			 //可以这样理解:num< 0 或者 num> 7,只要有一个条件为真就会执行语句
	{								//假设输入的num是-1,num小于0,结果为真,就会打印出:不是1到7的范围
		printf("不是1到7的范围\n"); // 要是输入的num是8,num>0了,是假,就会继续执行后面的判断语句,num>7,还是会打印出:不是1到7的范围
	}
	else
	{									//要是输入的是1到7之间的数值,则会打印:是1到7的范围
		printf("是1到7的范围\n");
	}

如果还不明白的话,举个例子:如果要去约会,是不是得同时2个人进行才能算是约会,要是只有一个人能算约会吗? &&逻辑与操作符就是这个道理,缺一不可,都为真才可以。

那 || 逻辑或该怎么理解呢?有一天,你暗恋许久的女神突然跟你说:只要你考上了大学或者能多财多亿的话我就做你女朋友。只要满足一个条件就能抱得女神归,逻辑或操作符就是这样的道理,只要有一个条件为真就可以。 

8.条件操作符

表达式1 ? 表达式2:表达式3

C语言——操作符详解_第13张图片

 求两个数的较大值,条件操作符就可以派上用场了。

int a = 5;
	int b = 8;
	int max = (a > b ? a : b);	//a如果大于b的话会把a赋值给max,如果a不大于b 的话则会把b赋值给max
	printf("%d\n", max);

C语言——操作符详解_第14张图片

 9.逗号表达式

exp1, exp2, exp3, …expN

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

	int a = (1, 2, 3, 5);	//逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
							//整个表达式的最后是5,5最终赋值给a
	printf("%d\n", a);

C语言——操作符详解_第15张图片

 10.下标引用、函数调用和结构成员

1. [ ]  下标引用操作符(就是数组使用的下标引用符)
操作数:一个数组名 + 一个索引值

int arr[10] = { 1,2,3,4,5,6,7,8,9,10};	//创建数组

	printf("%d\n", arr[5]);    //打印数组下标为5的元素

C语言——操作符详解_第16张图片

2.访问一个结构的成员

.            结构体.成员名
->          结构体指针->成员名

struct stu
{
	char name[20];
	int age;
};
int main()
{
	struct stu s1 = { "李四", 19 };
	printf("%s  %d\n", s1.name, s1.age);	// .是用来访问结构体成员的
	return 0;
}

C语言——操作符详解_第17张图片

struct stu
{
	char name[20];
	int age;
};
int main()
{
	struct stu s1 = { "李四", 19 };
	struct stu* p = &s1;

	printf("%s  %d", p->name, p->age);		//打印结构体指针指向的成员

	return 0;
}

C语言——操作符详解_第18张图片

你可能感兴趣的:(c语言,操作符)