目录
前言
引例
1.操作符的分类
2.算术操作符
3.移位操作符
3.1左移操作符
3.2右移操作符
4.位操作符
5.赋值操作符
6.单目操作符
6.1单目操作符介绍
6.2sizeof和数组
7.关系操作符
8.逻辑操作符
9.条件操作符
10.逗号表达式
11.下标引用、函数调用和结构成员
12.表达式求值
12.1隐式类型转换
12.2算术转换
12.3操作符的属性
前言
操作符是我们在编写c代码时频繁使用的,但是我发现很多小伙伴除了对算术操作符和赋值操作符有简单的了解外,对其他的操作符知之甚少,以至于经常因操作符的错误使用写出一些令人头疼的bug。除了经常用到的这两种操作符,我们还要学会一些不经常使用,但是考试会考,并且功能强大的操作符。
引例
1.不通过创建临时变量完成两个变量的值交换可以用几种方式实现?
2.int a = 1; int b = 2; int c = (a > b, a = b + 10, a, b = a + 1); //c是多少?
3.int a = -10; printf("%d\n", sizeof a);//这样写行不行?
接下来我们拭目以待~
正文
1.操作符的分类
算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式
下标引用、函数调用和结构成员
接下来我们一一介绍
2.算术操作符
+ - * / %
算术操作符我们经常用到,我们只需要注意以下三点:
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有一个浮点数执行的就是浮点数除法,其结果就为浮点数
3. % 操作符的两个操作数必须为整数。
3.移位操作符
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
介绍移位操作符之前,我们得先清楚一个概念:
整数在内存中存储的是二进制的补码
移位操作符,移动的是一个整数在内存中的补码
因此移位操作符的对象只能是整数
3.1左移操作符
移位规则:
左边抛弃、右边补0
下面做展示:
需要注意的是,将num左移之后,num本身的值并没有变,类似于num+1但是num本身并没有变,但如果是这样
int num = 10; num = num + 1; num = num << 1;
移位之后再赋值给自己,就可以改变。
3.2右移操作符
移位规则:
首先右移运算分两种:
1. 逻辑移位
左边用0填充,右边丢弃
2. 算术移位
左边用原该值的符号位填充,右边丢弃
警告⚠:
对于移位运算符,不要移动负数位,这个是标准未定义的。
例如:
int num = 10;
num>>-1;//error
4.位操作符
位操作符有:
& //按位与
| //按位或
^ //按位异或
注:他们的操作数必须是整数,使用对象为内存中二进制的补码
&:左右两边都为1,结果才是1。只要有一个为0,结果就是0。
|:左右两边都为0,结果才是0。只要有一个为1,结果就是1。
^:左右两边相同,结果为0,左右两边不同,结果为1。
简单展示:
#include <stdio.h> int main() { printf("%d\n", 1 & 1);//1 printf("%d\n", 1 & 0);//0 printf("%d\n", 0 & 0);//0 printf("****************\n"); printf("%d\n", 0 | 1);//1 printf("%d\n", 1 | 1);//1 printf("%d\n", 0 | 0);//0 printf("****************\n"); printf("%d\n", 1 ^ 1);//0 printf("%d\n", 1 ^ 0);//1 printf("%d\n", 0 ^ 0);//0 return 0; }
一道变态的面试题:
不能创建临时变量(第三个变量),实现两个数的交换。
1.#include <stdio.h> int main() { int a = 10; int b = 20; a = a ^ b; b = a ^ b; a = a ^ b; printf("a = %d b = %d\n", a, b); return 0; }
我们可以自己尝试着理解一下代码的实现逻辑,实在不明白的小伙伴可以私信我哦。
5.赋值操作符
赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
int 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; //这样的写法是不是更加清晰爽朗而且易于调试。
复合赋值符
+=
-=
*=
/=
%=
>>=
<<=
&=
|=
^=
这些运算符都可以写成复合的效果。
比如:
int x = 10; x = x + 10; x += 10;//复合赋值 //其他运算符一样的道理。这样写更加简洁。
6.单目操作符
6.1单目操作符介绍
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
这里有几个初学者不经常用,但是后期会用到的操作符:
!:逻辑反操作符,顾名思义,将逻辑真与假互换。例如,!0=1,!1=0。
&:取地址操作符,顾名思义,取出某个变量的地址。
~:对一个数的二进制按位取,如:~101010(二进制)=010101(二进制)。
*:解引用操作符(也有乘的意思),后面指针的章节会讲。
(类型):强制类型转换。如:
int n=10; float m=0.0f; m=(float)n;
前置++与后置++的区别
前置++:先++在使用。
例如:
#inculde<stdio.h> int main()n {n int n = 0; printf("%d\n", ++n);//结果为1 //先对n进行自增,然后再使用n,也就是表达式的值是n自增之后的值。 return 0; }n
后置++:先使用再++。
例如:
#include<stdio.h> int main() { int n = 0;n printf("%d", n++);//结果为0 printf("%d", n);//结果为1 //先对n使用,再增加,这样打印的值是0;之后n变成1; return 0; }
前置--与后置--效果相同
6.2sizeof和数组
sizeof()是一个 操作符,并非库函数。其作用是用来计算大小,单位是 字节。
例如我们可以计算某个变量的大小:
#include<stdio.h> int main() { int n = 0; float m = 2.0f; double q = 3.14f; long long l = 12345; printf("%d\n", sizeof(n));//4 printf("%d\n", sizeof(m));//4 printf("%d\n", sizeof(q));//8 printf("%d\n", sizeof(l));//8 return 0; }
或者是某种类型的大小:
#include<stdio.h> int main() { printf("%d\n", sizeof(int));//4 printf("%d\n", sizeof(float));//4 printf("%d\n", sizeof(double));//8 printf("%d\n", sizeof(long long));//8 return 0; }
或者是数组的大小:
#include<stdio.h> int main() { int arr1[10] = { 0 }; char arr2[5] = { '0' }; char str[] = "hello"; //数组大小为数组每个元素的大小*数组元素个数 printf("%d\n", sizeof(arr1)); printf("%d\n", sizeof(arr2)); printf("%d\n", sizeof(str));//字符串后默认有'/0',占一个字节 return 0; }
#include <stdio.h> void test1(int arr[]) { printf("%d\n", sizeof(arr));//(2) } 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));//(3) test1(arr); test2(ch); return 0; }
问:
( 1 )、( 2 )两个地方分别输出多少?
( 3 )、( 4 )两个地方分别输出多少?
那么我们这个问题就很容易了。但是当我们运行之后却可能得到出人意料的结果。
其中(1)(3)的结果如我们所想,但是(2)(4)却不一样。
如果小伙伴们还记得我之前所讲,数组传参时,传递的是数组的首地址,那么原因就不难理解了。
既然是地址,那地址的大小如何计算呢?
1.在64位机器上,指针(指针就是地址)的大小统一为8字节。
2.在32位机器上,指针(指针就是地址)的大小统一为4字节.
所以小伙伴们运行之后得到的结果就是4或者8了。
sizeof的其他格式:
#include <stdio.h> int main() { int a = -10; printf("%d\n", sizeof a);//这样写行不行? printf("%d\n", sizeof int);//这样写行不行? return 0; }
至于结果可自行测试。