操作符不算难,但是新手使用的时候总会忘记操作符具体有哪些,故作此篇文章,简单汇总一下操作符结论。(不会解释为什么,适合刚学不久的人用来回顾知识点)
相关汇总文章链接放在最后。
目录
1· 算数操作符
2·移位操作符
3·位操作符
4.赋值操作符
5·单目操作符
6·关系操作符
7·逻辑操作符
8·条件操作符(三母操作符)
9·逗号表达式
10·下标引用、函数调用和结构成员
汇总链接
算数操作符几乎和我们数学中的加减乘除差不多,如表。
+ | - | * | / | %(取余) |
a+b | a-b | a*b | a/b | a%b |
%就是取余数的意思,9%6 = 3,也就是9除6之后的余数为3~
重要结论:
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
例子展示:
int main()
{
int a = 9 / 2; //4
float b = 9 / 2; //4.000000
float c = 9.0 / 2; //4.500000
int d = 9.0 / 2; //4 执行浮点数除法,用int储存会丢失精度
float e = 9 / 2.0; //4.500000
float f = 9 % 2; //1.000000
int g = 6 / 2.5; //2 执行浮点数除法,用int储存会丢失精度
printf("%f\n", 6 / 2.5); //2.400000
return 0;
}
移位操作符,从名字可以知道,移动的是二进制位(补码中的二进制位)。
<<左移 | >>右移 |
左边不要,右边补0 | 1.逻辑移位:左边补0、右边丢弃 2. 算术移位:左边用原该值的符号位填充,右边丢弃 计算机系统中的右移以算术移位为主。 |
对于移位运算符,不要移动负数位,这个是标准未定义的。
例如:
int aqiu = 10;
num>>-1; //这是不可以的哦!
重要结论:
1.操作数必须是整数。也就是说不能<<2.3。
2.位操作符是对补码进行移位操作。
3·别的变量储存它按位后的结果或者放在判断条件中,它本身不变。(如图)
例子展示:
int main()
{
int a = 2;
//00000000000000000000000000000010
int b = a << 1;
//00000000000000000000000000000100
//左移:左边不要,右边补0
int d = a >> 1;
//00000000000000000000000000000001
//右移:左边用原该值的符号位填充,右边丢弃
int e = -1;
//11111111111111111111111111111111
int f = e >> 1;
//11111111111111111111111111111111
//右移:左边用原该值的符号位填充,右边丢弃
return 0;
}
位操作符顾名思义,也是对二进制位操作(补码形式的二进制)。
& | 按位与(有0为0) |
| | 按位或(有1为1) |
^ | 按位异或(相同为0,不同为1) |
异或的结论:
1· 任何两个相同的数 异或 为0
2· 任何数字和0 异或 是它本身
异或例子展示:不创建中间变量,交换两个数的值
int main()
{
int a = 3;
int b = 5;
//交换a和b的值
a = b ^ a;
b = b ^ a;
//相当于b=b^b^a
//b^b=0,0^a=a
//此时b=a
a = a ^ b;
//相当于b^a^a
//此时a=b
printf("a=%d,b=%d", a, b);
//a=5;b=3;交换成功
return 0;
}
重要结论:
1.和移位运算符一样,他们的操作数也必须是整数。也就是说不能&、|、^2.3
2.和移位运算符一样,位操作符也是对补码进行操作。
3·和移位运算符一样,别的变量储存它按位后的结果或者放在判断条件中,它本身不变。
&操作符常用于:统计二进制中 1 的个数
//方法1: n & (1 << i)或者n & (1 << i)
int count_one_bit(unsigned int n)
{
int count = 0;
int i = 0;
for (i = 0; i < 32; i++) //32位系统是32bit位
{
if ((n >> i) & 1)
count++;
//或者
//if( n & (1 << i))
//count++;
}
return count;
}
//方法2:采用相邻的两个数据进行按位与运算
int count_one_bit(int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
& 和 ^ 常涉及练习题:求两个数二进制中不同位的个数
方法1: 使用异或^后的p & (1 << a)求不同位
int main()
{
int i = 0;
int j = 0;
scanf("%d %d", &i, &j); //scanf需要指针类型的参数
int p = i ^ j;
//异或,不同为1
//算有几个1,就是两个数二进制中不同位的个数
int a = 0;
int count = 0;
for (a = 0; a < 32; a++)
{
if (p & (1 << a))
{
count++;
}
}
printf("%d\n", count);
return 0;
}
方法2:使用异或^后的a = a&(a-1)求不同位
int calc_diff_bit(int m, int n)
{
int tmp = m ^ n;
int count = 0;
while (tmp)
{
tmp = tmp & (tmp - 1);
count++;
}
return count;
}
int main()
{
int m, n;
while (scanf("%d %d", &m, &n) == 2)
{
printf("%d\n", calc_diff_bit(m, n));
}
return 0;
}
“=”
这是赋值操作符,并不是等于。c语言中的等于是"=="。简单来说,我们常用的int a=3;这就是把3赋值给a了。
复合赋值符
+= -= *= /= %=>>= <<= &= |= ^=
int a = 0;
a = a + 3;
//也可以写成下面这样
a += 3;
a = a % 3;
//也可以写成下面这样
a %= 3;
! 逻辑反操作
规定0为假,非0为真
!逻辑取反就是真假互换,一般0会变为1,非0变为0
例子展示:
int main()
{
int flag = 0; //flag为假
if (flag)
{
printf("1"); //不能打印,因为flag为假
}
//flag为假的时候进行打印
if (!flag) //!falg把假的flag变为真,执行语句
{
printf("2");
}
return 0;
}
sizeof 操作数的类型长度(以字节为单位)
1.siizeof是一个操作符,而不是函数(函数不能省略括号)
2.sizeof可以计算类型或者变量所占空间的大小,sizeof的单位是字节
常涉及到的问题放在代码中:
1·括号省略问题与数组大小计算
int a;
printf("%d\n", sizeof(a)); //ok
printf("%d\n", sizeof(int)); //ok
printf("%d\n", sizeof a); //ok
printf("%d\n", sizeof int); //这个不行
//不能省略类型的括号
//sizeof可以省略变量的括号,说明它只是一个操作符而不是函数
//因为函数的括号不能省略,而sizeof可以省略变量的括号
int arr[10];
//计算整个数组的大小
printf("%d\n", sizeof(arr));
//int [10]就是数组的类型,代表整个数组
printf("%d\n", sizeof(int[10]));
2·数组传参与sizeof
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//结果:4
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//结果:1
}
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;
}
3·sizeof括号中的表达式不参与运算
//计算的是如果表达式参与运算后的类型大小
int main()
{
short i = 5;
int j = 6;
long long p = 9;
printf("%d\n", sizeof(i = j + 2)); //4
printf("%d\n", i); //i依旧=5
printf("%d\n", sizeof(i+j)); //4
printf("%d\n", sizeof(p+i)); //8
//表达式的类型是看左值的类型
printf("%d\n", sizeof(p=i+j)); //8
return 0;
}
~ 对一个数的二进制按位取反(包括符号位)
移位操作符(<<、>>)和位操作符(&、|、^)和单目操作符 ~ 都是
1.操作数是整数。
2.对补码进行操作。
3·别的变量储存它按位后的结果或者放在判断条件中,它本身不变。
综合运用:把a=13的二进制补码1101前面的0变为1后,再变为0。
int main()
{
int a = 13;
//能把1101前面的0变为1
a = a | (1 << 4);
//00001101 a
//00010000 1 << 4
//00011101 a | (1 << 4)
//这样就能把1101前面的0变为1
//把1101前面的1变为0
//第一种
a = a ^ (1 << 4);
//00011101 a
//00010000 1 << 4
//00001101 a ^ (1 << 4)
//第二种
a = a & ~(1 << 4);
//00010000 1 << 4
//11101111 ~(1 << 4)
//00011101 a
//00001101 a & ~(1 << 4)
//&=~是置0 ,|= 是置1
return 0;
}
前置、后置的--、++
int main()
{
int a = 2;
int b = a++; //后置++,先使用,后+
printf("%d\n", a); //3
printf("%d\n", b); //2
int c = 3;
int d = ++c; //前置++,先+,后使用
printf("%d\n", c); //4
printf("%d\n", d); //4
return 0;
}
&取地址和* 间接访问操作符(解引用操作符)
&就是取出地址的操作符,*则是通过指针(储存的地址)去访问这个地址住着的人。
int a = 1;
int* p = &a;
*p = 2;
*(&a) = 9;
&a是a的地址;p是指针变量,存放了a的地址。
*p和*(&a)代表通过地址访问住户a。
> 大于
>= 大于等于
< 小于
<= 小于等于
!= 用于测试“不相等”
== 用于测试“相等”
注意: 在编程的过程中 == 和 = 所代表的意思不一样!!!
&& 逻辑与 | || 逻辑或 | |
原则 | 一假则假 | 一真则真 |
和&、|区别 | &与|是对二进制中的补码进行操作, 而&&与||是对前后表达式的结果(真假)进行操作。 |
|
计算原则 | 遇假停算 | 遇真停算 |
全部计算 | 全部为真,或者最后一个为假 | 全部为假,或者最后一个为真 |
可能表格中你看不懂,这里展开说一下:
什么情况下停止计算?
&&一假则假,碰到一个假的就不再计算。
|| 一真则真,碰到一个真的就不再计算。
什么情况下才会把&&或者||连接的表达式都计算呢?
&&全部为真,或者最后一个为假。
|| 全部为假,或者最后一个为真。
exp1 ? exp2 : exp3
exp1是判断条件,为真执行exp2,为假执行exp3
exp就是表达式的意思。
int main()
{
int a = 3;int b = 0;int c = 5;
c = a < b ? a : b; //这就是条件操作符,也叫三目操作符
//输出结果:c = 3
}
exp1, exp2, exp3, …expN 用逗号隔开的多个表达式。
从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
if (a = b + 1, c = a / 2, d > 0);
//虽然表达式的结果是最后一个,但是需要从左向右计算
//即使前边的表达式结果为假,依旧会向后计算
//以最后一个表达式结果为标准。
int d = (a = 9 + c, b = a, c = a + b+ c);
//以最后一个表达式结果为标准。
小用途:简化代码
a = get_val();
count_val(a);
while (a > 0)
{
//其他语句
a = get_val();
count_val(a);
}
//简化
while (a = get_val(), count_val(a), a>0)
{
//其他语句
}
[ ] 下标引用操作符
( ) 函数调用操作符
访问一个结构的成员:
结构体 . 成员名
-> 结构体 指针 ->成员名
//1.[ ] 下标引用操作符
arr[9] = 10;//实用下标引用操作符。
[ ]的两个操作数是arr和9。
//2. ( ) 函数调用操作符
void test1(){}
void test2(const char *str){}
int main(){
test1(); //用()作为函数调用操作符。
test2("hello");//用()作为函数调用操作符。
return 0;
}
//3. 访问一个结构的成员
struct Stu stu;
struct Stu* pStu = &stu;
//1·结构体.成员名
stu.age = 20;//结构成员访问
//2·指针才可以用->结构成员访问
pStu->age = 20;//结构成员访问
至此,结束~
从0开始学c语言-07-认识一下操作符、原码和反码和补码_阿秋的阿秋不是阿秋的博客-CSDN博客
从0开始学c语言-18-操作符详解_阿秋的阿秋不是阿秋的博客-CSDN博客
从0开始学c语言-26-操作符练习、指针练习、调试作业_阿秋的阿秋不是阿秋的博客-CSDN博客