【初阶C语言】操作符详解总结(万字)(一)

简介: 【初阶C语言】操作符详解总结(万字)(一)

1. 操作符分类


算术操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

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


2. 算术操作符


+, -, * , / ,%


除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。

对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。

% 操作符的两个操作数必须为整数。返回的是整除之后的余数。

#include <stdio.h>
int main()
{
  //  / 除法 - 得到的是商
  // 除法操作符的两个操作数都是整数的话,执行的是整数除法
  // 除法操作符的两个操作数只要有一个浮点数,执行的是小数除法
  // 
  //  % 取模( 取余)得到的是余数
  //  取模操作符的操作数必须是整数
  printf("%lf\n", 10 / 3.0);//5
  printf("%d\n", 10 % 2);//0
  return 0;
}


3. 移位操作符


左移操作符<<

右移操作符>>

注:移位操作符的操作数只能是整数。


3.1 整数的二进制是怎么形成的

整数的二进制表示形式有三种:原码,反码,补码


原码:把一个数按照正负直接翻译成二进制就是原码

反码:原码的符号位不变,其他位按位取反就是反码

补码:反码+1


注意:


正整数的原码,反码,补码是相同的

负整数的原码,反码,补码是要计算的

最高的一位表示符号位,0表示正数,1表示负数

整数在内存中储存的是补码(二进制)

原码到补码是取反+1,补码到原码是取反+1或-1取反。


3.2 左移操作符

移位规则:


左边抛弃、右边补0

int main()
{
  int a = -3;
  //10000000000000000000000000000011
  //11111111111111111111111111111100
  //11111111111111111111111111111101 - 补码
  //
  int b = a << 1;
  //11111111111111111111111111111010
  //11111111111111111111111111111001
  //10000000000000000000000000000110
  //11111111111111111111111111111010
  //10000000000000000000000000000101
  //10000000000000000000000000000110
  printf("%d\n", b);//-6
  printf("%d\n", a);//-3
  return 0;
}


3.3 右移操作符

移位规则:

首先右移运算分两种:


逻辑移位

左边用0填充,右边丢弃

算术移位

左边用原该值的符号位填充,右边丢弃

右移的时候,到底采用的是算数右移还是逻辑右移,是取决于编译器的!

//>> 右移操作符
//VS:算术右移
int main()
{
  int a = -5;
  //10000000000000000000000000000101
  //11111111111111111111111111111010
  //11111111111111111111111111111011
  //
  int b = a >> 1;
  //11111111111111111111111111111101
  //11111111111111111111111111111100
  //10000000000000000000000000000011
  //-3
  printf("b = %d\n", b);
  printf("a = %d\n", a);//-5
  return 0;
}


警告⚠:

对于移位运算符,不要移动负数位,这个是标准未定义的。

例如:

int num = 10;
num>>-1;//error


4. 位操作符


位操作符有:


& 按位与

| 按位或

^ 按位异或

注:他们的操作数必须是整数。


int main()
{
  int a = 3;
  int b = -5;
  int c = a ^ b;//按位异或 - 对应的二进制位,相同为0,相异为1
  //11111111111111111111111111111011 - -5的补码
  //00000000000000000000000000000011 - 3的补码
  //11111111111111111111111111111000
  //11111111111111111111111111110111
  //10000000000000000000000000001000 - 结果为-8
  int c = a | b;//按位或 - 有1则是1
  //11111111111111111111111111111011 - -5的补码
  //00000000000000000000000000000011 - 3的补码
  //11111111111111111111111111111011 - 结果为-5
  int c = a & b;//按位与 - 两个都是1,结果才为1
  //00000000000000000000000000000011 - 3的补码
  //10000000000000000000000000000101 - 5的原码
  //11111111111111111111111111111010
  //11111111111111111111111111111011 - -5的补码
  //00000000000000000000000000000011 - 3的补码
  //00000000000000000000000000000011 - 结果为3
  printf("%d\n", c);
  return 0;
}


一道变态的面试题:


编写代码实现:不能创建临时变量(第三个变量),实现两个数的交换。


int main()  //三种方法,其中第三种是不需要临时变量的
{
  int a = 3;
  int b = 5;
  //int tmp = 0;
  printf("交换前:a=%d b=%d\n", a, b);
  //3
  //a = a ^ b;
  //b = a ^ b;
  //a = a ^ b;
  //2
  /*a = a + b;
  b = a - b;
  a = a - b;*/
  //1
  //tmp = a;
  //a = b;
  //b = tmp;
  printf("交换后:a=%d b=%d\n", a, b);
  return 0;
}


练习:


编写代码实现:求一个整数存储在内存中的二进制中1的个数。


int main()        //思路
{
  int a = 11;
  a & 1;
  a = a >> 1;
  //00000000000000000000000000001011
  //00000000000000000000000000000001
  //00000000000000000000000000000001
  return 0;
}
//方法1
#include <stdio.h>
int main()
{
  int num = 10;
  int count = 0;//计数
  while (num)
  {
  if (num % 2 == 1)
    count++;
  num = num / 2;
  }
  printf("二进制中1的个数 = %d\n", count);
  return 0;
}
//思考这样的实现方式有没有问题?
//方法2:
#include <stdio.h>
int main()
{
  int num = -1;
  int i = 0;
  int count = 0;//计数
  for (i = 0; i < 32; i++)
  {
  if (num & (1 << i))
    count++;
  }
  printf("二进制中1的个数 = %d\n", count);
  return 0;
}
//思考还能不能更加优化,这里必须循环32次的。
//方法3:
#include <stdio.h>
int main()
{
  int num = -1;
  int i = 0;
  int count = 0;//计数
  while (num)
  {
  count++;
  num = num & (num - 1);
  }
  printf("二进制中1的个数 = %d\n", count);
  return 0;
}
//这种方式是不是很好?达到了优化的效果,但是难以想到。

相关文章
|
1月前
|
存储 C语言 索引
【C语言篇】操作符详解(下篇)
如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。
|
1月前
|
程序员 编译器 C语言
【C语言篇】操作符详解(上篇)
这是合法表达式,不会报错,但是通常达不到想要的结果, 即不是保证变量 j 的值在 i 和 k 之间。因为关系运算符是从左到右计算,所以实际执⾏的是下⾯的表达式。
|
1月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
36 6
|
1月前
|
存储 编译器 C语言
十一:《初学C语言》— 操作符详解(上)
【8月更文挑战第12天】本篇文章讲解了二进制与非二进制的转换;原码反码和补码;移位操作符及位操作符,并附上多个教学代码及代码练习示例
47 0
十一:《初学C语言》—  操作符详解(上)
|
2月前
|
C语言
五:《初学C语言》— 操作符
本篇文章主要讲解了关系操作符和逻辑操作符并附上了多个代码示例
37 1
五:《初学C语言》—  操作符
|
2月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
2月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上
|
3月前
|
C语言
C语言逻辑操作符的短路问题
C语言逻辑操作符的短路问题
|
3月前
|
编译器 C语言
【C语言】:中移位操作符,位操作符详运算规则详解
【C语言】:中移位操作符,位操作符详运算规则详解
30 1
|
3月前
|
算法 C语言
【C语言】:巧用移位操作符,位操作符解决问题
【C语言】:巧用移位操作符,位操作符解决问题
28 0