操作符详解

简介: 目录1. 算数操作符2. 移位操作符 2.1 右移操作符 2.2 左移操作符3. 位操作符4. 赋值操作符5. 单目操作符6. 关系操作符7. 逻辑操作符8. 条件操作符9. 逗号表达式10.下标引用、函数调用和结构成员

1.   算数操作符

如:+    -   *   /   %

这里着重讲解下 / 和 % 操作符,上代码:

#include<stdio.h>
int main()
{
  int m = 10 % 3;      //    %---取余(两端必须是整数)
  printf("%d\n", m);   //    1
  int n = 10 / 3;      //    /---取商
  printf("%d\n", n);   //    3
  //  当 /(除号)两端是整数的时候,执行的是整数的除法,两端只要有一个浮点数,执行的就是浮点数的除法
  double z = 10.0 / 3;
  printf("%lf\n", z);  //    3.333333
  return 0;
}

image.png2.   移位操作符

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


引言:


整数有3种二进制的表示形式

1:原码    

2:反码      

3:补码

对于正整数 - 原码 - 反码 - 补码 均相同

对于负整数 - 原码 - 反码 - 补码 不同,要进行计算!

如+5:   整数,整型,32bit

  00000000000000000000000000000101  ---原码---反码---补码

如-5:    整数,负数

  10000000000000000000000000000101  ---原码

  11111111111111111111111111111010  ---反码(原码的符号位不变,其他按位取反)

  11111111111111111111111111111011  ---补码(反码的二进制+1)

整数在内存中存储的是补码!!!


     2.1  右移操作符  (>>)

移位规则: 首先右移运算分两种:


1. 逻辑移位 (左边用0填充,右边丢弃)


2. 算术移位 (左边用原该值的符号位填充,右边丢弃)

#include<stdio.h>
int main()
{
  int a = 5;
  int b = a >> 1;
  printf("%d\n", b);    //输出2
  return 0;
}

我们来画张图解释下吧:

image.png

     2.2  左移操作符 (<<)

原理同右移操作符

移位规则: 左边抛弃、右边补0

上代码:

#include<stdio.h>
int main()
{
  int a = 5;
  //把a在内存中存储的二进制位向左移动2位
  int b = a << 2;
  //此时此刻b的二进制为00000000000000000000000000010100
  //换成10进制表示20
  printf("%d", b);//打印或使用用的是原码的值   20
  return 0; 
}

3.   位操作符

  &  按位与

  |   按位或

  ^  按位异或

//   -5的原码  10000000000000000000000000000101  

//   -5的反码  11111111111111111111111111111010  

//   -5的补码  11111111111111111111111111111011  

//    3的补码  00000000000000000000000000000011

//    &按位与:有0为0,全1为1。

//    c = -5&3:    00000000000000000000000000000011

//    c的内存存的是补码,打印的是原码  上述补码是正数,原码反码补码相同

//    |按位或:有1为1,全0为0

//    ^相同为0,相异为1

//    c的内存存的是补码,打印的是原码


上代码:


#include<stdio.h>
int main()
{
  int a = 3;
  int b = -5;
  int m = a & b;
  int n = a | b;
  int k = a ^ b;
  printf("%d\n", m);   // 3
  printf("%d\n", n);   // -5
  printf("%d\n", k);   // -8
  return 0;
}

画图解析:

image.png

image.png

//练习:

//交换两个整型变量(不能创建临时变量)

法一:临时变量法 效率高

#include<stdio.h>
int main()
{
  int a = 3;
  int b = 5;
  int c = 0;
  printf("交换前a=%d b=%d\n", a, b);   //交换前a=3 b=5
  c = a;
  a = b;
  b = c;
  printf("交换后a=%d b=%d\n", a, b);   //交换后a=5 b=3
  return 0;
}

法二:(此法存在溢出的问题)

#include<stdio.h>
int main()
{
  int a = 3;
  int b = 5;
  a = a + b;
  b = a - b;
  a = a - b;
  printf("a=%d b=%d", a, b);
  return 0;
}

法三:异或操作符 (仅限于整数)

//     3^3=0

//     0^5=5

#include<stdio.h>
int main()
{
  int a = 3;
  int b = 5;
  a = a ^ b;
  b = a^ b;  //即为  a ^ b ^ b = a ^ 0 = a
  a = a ^ b; //即为  a ^ a ^ b = 0 ^ b = b
  printf("a=%d b=%d", a, b); 
}

image.png

4.  赋值操作符

赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。

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;//复合赋值
//其他运算符一样的道理。这样写更加简洁。

5.   单目操作符

image.png

! (逻辑反操作)

#include<stdio.h>
int main()
{
  int flag = 0;
  if (!flag)
    printf("hehe\n");  // hehe
  return 0; 
}

 -(负值)

#include<stdio.h>
int main()
{
  int i = 0;
  int flag = 1;
  for (i = 0; i < 10; i++)
  {
    printf("%d ", i * flag);
    flag = -flag;
  }
  return 0;
}
// abs  对整数求绝对值
// fabs 对小数求绝对值

image.png sizeof(操作符的类型长度,以字节为单位)

#include<stdio.h>
int main()
{
  int a = 10;
  printf("%d\n", sizeof(a));    //4字节
  printf("%d\n", sizeof(int));  //4字节
  int arr[10] = { 1,2,3,4,5,6 };
  printf("%d\n", sizeof(arr));  //40字节
  printf("%d\n", sizeof(int[10]));  //40字节
}

 ~ 按位取反

#include<stdio.h>
int main()
{
  int a = 0;
  // ~ 按(内存中补码的二进制)位取反
  // 00000000000000000000000000000000
  // 11111111111111111111111111111111   补码
  // 11111111111111111111111111111110   反码
  // 10000000000000000000000000000001   原码
  printf("%d\n", ~a);   // -1
  return 0;
}
#include<stdio.h>
int main()
{
  int a = 10;
  // 00000000000000000000000000001010  
  // 00000000000000000000000000000100    ---   1<<2得到左边
  // 00000000000000000000000000001110
  // 11111111111111111111111111111011    ---   ~(1<<2)
  // 00000000000000000000000000001010
  a = a | (1 << 2);
  printf("%d\n", a);   // 14
  a = a & ~(1 << 2);
  printf("%d\n", a);   // 10
  return 0;
}

++ 和 -- 运算符

上代码:

#include<stdio.h>
int main()
{
  int a = 3;
  int b = a++;   //后置++ ,先使用,后++
  printf("a= %d,b=%d\n", a, b);   // a=4  b=3
  return 0;
}
#include<stdio.h>
int main()
{
  int a = 3;
  int b = ++a;  //前置++,  先++,后使用
  printf("a=%d b=%d\n", a, b);  // a=4,b=4
  return 0;
}
 //--类似

* 简介访问操作符(解引用操作符)

#include<stdio.h>
int main()
{
  int a = 10;
  int* p = &a;
  *p = 120;   // *p解引用操作符
  printf("%d\n", a);    // 120
  return 0;
}

()强制类型转换

#include<stdio.h>
int main()
{
  int a = (int)3.14;  //3.14 - double -> int a
  printf("%d\n", a);  // 3
  return 0;
}

练习:

#include<stdio.h>
int main()
{
  int a = 10;
  int* p = NULL;
  printf("%d\n", !2);    // 0
  printf("%d\n", !0);    // 1
  a = -a;
  p = &a;
  printf("%d\n", sizeof(a)); // 4
  printf("%d\n", sizeof(int)); // 4
  printf("%d\n", sizeof a);  // 4
  //printf("%d\n", sizeof int); err
}
#include<stdio.h>
void test1(int arr[])
{
  printf("%d\n", sizeof(arr));  //(2) 4
}
void test2(char ch[]) 
{
  printf("%d\n", sizeof(ch));   //(4) 4
}
int main()
{
  int arr[10] = { 0 };
  char ch[10] = { 0 };
  printf("%d\n", sizeof(arr));  //(1)  40
  printf("%d\n", sizeof(ch));   //(3)  10
  test1(arr);
  test2(ch);
  return 0;
}

6.   关系操作符

image.png

7.   逻辑操作符

&&     逻辑与

||        逻辑或

要特别区分逻辑操作符和位操作符,&&相当于是两个条件都要满足才可完成的指令,而||相当于两个条件只要有一个完成就可以。

//代码一:逻辑与
#include<stdio.h>
int main()
{
  int age = 0;
  scanf("%d", &age);
  if (age > 0 && age < 18)
  {
    printf("未成年\n");
  }
  return 0;
  return 0;
}
//代码二:逻辑或
#include<stdio.h>
int main()
{
  int month = 4;
  if (month < 1 || month>12)
  {
    printf("输入错误\n");
  }
  else
  {
  }
}
// 小练习:
#include<stdio.h>
int main()
{
  int i = 0, a = 0, b = 2, c = 3, d = 4;
  i = a++ && ++b && d++;
  //134行代码好比老师让三个同学都去完成一个任务,若其中任何一个没完成,就算任务失败
  //当a++时,先使用=0,为假,则后面不予考虑
  printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d); //  1 2 3 4
  //i = a++ || ++b || d++;
  若有一个满足,后面不予考虑
  //printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d); //  2 2 3 4
  return 0;
}

8.   条件操作符

image.png

#include<stdio.h>
int main()
{
  int a = 10;
  int b = 20;
  int max = 0;
  max = (a > b ? a : b);
  /*if (a > b)
  {
    max = a;
  }
  else
    max = b;*/
  printf("%d\n", max);   // 20
  return 0;
}

9.   逗号表达式

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

上代码:

//代码1
#include<stdio.h>
int main()
{
  int a = 3;
  int b = 5;
  int c = 6;
  int d = (a += 2, b = a - c, c = a + 2 * b);
  printf("%d\n", d);   // 3
  return 0;
}
//代码2
#include<stdio.h>
int main()
{
  int a = 1;
  int b = 2;  
  int c = (a > b, a = b + 10, a, b = a + 1);
  //  13
  printf("%d\n", c);   // 13
  return 0;
}

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

1:下标引用:

#include<stdio.h>
int main()
{
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
  printf("%d\n", arr[7]); // 8
  //arr[7]-- > * (arr + 7)-- > * (7 + arr)-- > 7[arr]
  //解释:因为arr是数组名,访问的的首元素的地址,arr+7即是第八个元素的地址,即 * (arr + 7)
  //      又因为加法交换律支持加号两边变换位置,即* (7 + arr),又可写成7[arr]。----装逼用
  printf("%d\n", arr[7]); // 8
  printf("%d\n", 7[arr]); // 8
  return 0;
}

2:函数调用:

#include<stdio.h>
void test()
{
  printf("hehe\n");
}
int Add(int x, int y)
{
  int z = 0;
  return z = x + y;
}
int main()
{
  test(); //函数调用操作符
  int ret = Add(2, 3);
  printf("%d\n", ret);
  return 0;
}

3: 结构成员访问操作符:

#include<stdio.h>
struct stu
{
  char name[20];
  int age;
  double score;
};
int main()
{
  struct stu s = { "zhangsan", 20, 85.5 };
  // .
  printf("%s %d %.1lf\n", s.name, s.age, s.score);   // 结构体变量.结构体成员
  // ->
  struct stu* ps = &s;
  printf("%s %d %.1lf\n", (*ps).name, (*ps).age, (*ps).score);  //此方法写起来过于繁琐
  printf("%s %d %.1lf\n", ps->name, ps->age, ps->score);  //运用->可较为方便
}
相关文章
|
9月前
|
存储 索引
【操作符】
【操作符】
25 0
|
10天前
|
编译器 C语言
操作符详解(1)
操作符详解(1)
16 0
|
10天前
|
编译器 Linux C语言
操作符详解(2)
操作符详解(2)
16 0
|
2月前
|
编译器 C语言 C++
操作符详解2(二)
本文介绍了编程中的操作符转换和表达式解析规则。当操作数类型不同时,会进行寻常算术转换,按照long double、double、float等类型顺序进行向上转换。表达式求值时,虽然操作符有优先级,但不能决定操作数的求值顺序,例如`a*b + c*d + e+f`中乘法先于加法,但具体计算顺序不确定,可能导致不同结果。同样,如`c++ + c--`这样的表达式也是有歧义的,因为++和--的左右结合性不能确定操作数的获取顺序。文章强调,复杂的表达式可能因编译器差异产生不同结果,应避免使用可能导致非唯一计算路径的表达式以减少潜在风险。
22 0
|
2月前
|
存储 程序员 C语言
操作符详解1(二)
该内容是一个关于C语言操作符和结构体的教程摘要。首先提到了加法操作符`+`的使用,并给出了一种不使用临时变量交换两个数的方法。接着讨论了如何计算整数的二进制表示中1的个数,通过位操作符实现。然后介绍了逗号表达式和函数调用操作符`()`,以及结构体成员访问操作符`.`和`-&gt;`,用于访问和修改结构体内的成员变量。文章以讲解结构体的声明、初始化和通过指针访问结构体成员为重点,展示了如何直接和间接地操作结构体数据。
23 0
|
7月前
|
存储 编译器
操作符详解(1)
操作符详解(1)
27 0
|
11月前
操作符详解(一)
操作符详解(一)
62 0
|
11月前
|
C语言 索引
【C】操作符详解
今天给大家带来一篇关于C语言操作符的详细介绍,在C语言中操作符主要有以下几种:
|
12月前
|
C语言 索引
详解操作符(中)
详解操作符(中)
|
12月前
|
存储