c语言操作符(上)

简介: c语言操作符(上)

一、算术操作符


算术操作符是最常见的,包括:


‘+’(加) ‘-’(减) ‘*’(乘) ‘/’(除) ‘%’(取余)


其中重点提一下‘/’(除)和‘%’(取余)操作符 ,其它3个太简单就不介绍了,相信大家都懂.


(1) .’ / '(除)操作符的除数(除号后面的数)不能为0,否则编译器会报错,毕竟这样不符合数学的规则了.电脑表示它不会算除数为0.😂


//除数b为0时会报错
#include <stdio.h>
int main()
{
  int a = 4, b = 0;
  int c = a / b;
  printf("%d", c);
  return 0;
}


(2).相除的结果是和数学中的一样吗?


#include <stdio.h>
int main()
{
  int a = 11, b = 4;
  int c = a / b;
  int d = a % b;
  printf("c=%d\n", c);
  printf("d=%d", d);
  return 0;
}


结果:


c=2
d=3


分析:c语言中的除法操作符结果只保留整数部分,而余数可以通过‘’%'(取余)操作符得到,这里11/4=2余3,所以有了上面的结果.


注意:!!!


除了‘’%‘(取余)操作符以外,其它操作符都可以用于浮点型., ’‘%’(取余)操作符的左右两个操作数必须为整数。返回的是整除之后的余数。


二、移位操作符


移位操作符的作用是什么呢?


其实"位"是指二进制位,所以移位操作符是指移动一个数的二进制位.


注意:!!!


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


说到二进制位,这就不得不提到二进制的三种形式


  • 原码


  • 反码


  • 补码


如果有不了解的小伙伴可以点击下面的传送门


(1) 左移操作符(‘<<’)


左移操作符即将操作数的二进制位向左移动


移动规则:


左边抛弃、右边补0(例题后面有效果图)


左移正数:


例如:将整形6左移两位


#include <stdio.h>
int main()
{
  int a = 6;
  printf("%d\n", a << 2);//将操作数a的二进制位向左移动两位
  printf("%d", a);//观察一下a本身的变化
  return 0;
}


运行结果:


24
6


结果分析:



将整形6左移两位后,得到的新的二进制序列表示的结果是:


0000 0000 0000 0000 0000 0000 0001 1000=24(十进制)


但是整形a的值并没有改变因为位移操作符并没有重新赋值,就如同:


printf("%d", -a);//打印结果虽然是-6,但是a本身的值并没有改变,还是6.


左移负数:


例如:将整形-6左移两位


#include <stdio.h>
int main()
{
  int a = -6;
  printf("%d\n", a << 2);//将操作数a的二进制位向左移动两位
  printf("%d", a);//观察一下a本身的变化
  return 0;
}


运行结果:


-24
-6


效果分析图:



通过上述示例,2我们不难发现,一般情况下,左移有翻倍的效果,左移一位的结果是原来的二倍,左移两位是原来的四倍.


(2) 右移操作符(‘>>’)


右移操作符即将操作数的二进制位向右移动


移位规则:


首先右移运算分两种:


  1. 逻辑移位


左边用0填充,右边丢弃


  1. 算术移位(一般使用这个)


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


右移正数


示例:


#include <stdio.h>
int main()
{
  int a = 10;
  printf("%d\n", a >> 1);//将操作数a的二进制位向右移动一位
  printf("%d", a);//观察一下a本身的变化
  return 0;
}


通过上面学习了操作符左移,那正数的操作符右移应该不难吧。试着猜一下结果吧。


运行结果;


5
10



这里采用的是算术右移,补位为符号位0.


右移负数:


#include <stdio.h>
int main()
{
  int a = -10;
  printf("%d\n", a >> 1);//将操作数a的二进制位向右移动一位
  printf("%d", a);//观察一下a本身的变化
  return 0;
}


-5
-10



这里采用的是算术右移,补位为符号位1.这里可以看出逻辑右移与算术右移的区别,如果采用逻辑右移,那么符号位补的就是0,负数就会变成正数,一般我们编译器采用的是算术右移.即左边抛弃,右边补符号位


总结:


左移有翻倍的效果,因为从效果图中可以看出,向左移动,数据位1代表的权重就会增加一倍,同样右移会减少到原来的二分之一.


注意:!!!


**其一:无论是左移还是右移,移动的位数不要太过火了,移动33位或者更多电脑表示无能为力

其二: 移动的位数不要是负数,否则是不是太奇怪了?


例如:<<-3是表示右移3位吗?并没有这种表示方法.**不要破坏规则哦.


三、位操作符


位操作符的分类:


& //按位与
| //按位或
^ //按位异或


注意:!!!


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


同样这里的位也是指二进制位.


1)& (按位与操作符):只有两边的操作数都为真的时候才为真,否则都为假.


2)’ | '(按位或操作符):只要一边为真则为真.


3)’ ^ '(按位异或操作符):相同为假,相异为真.



我要晕了😂,其实二进制只有0和1,咱只需要知道:


1)& (按位与操作符):只有都为1时才是1,其它都为0.


2)’ | '(按位或操作符):只要有1就是1,除非你都是0.


3)’ ^ '(按位异或操作符):相同(同0或同1)则就是0,不同就是1.


试着读代码算出结果吧!


#include <stdio.h>
int main()
{
  int x = 78, y = 23;
  int a = x & y;
  int b = x | y;
  int c = x ^ y;
  printf("a=%d\nb=%d\nc=%d", a, b, c);
  return 0;
}


运行结果:


a=6
b=95
c=89



学会位操作符和移位操作符后,试着练习一下两道经典的题目吧!


小试牛刀


四、赋值操作符


赋值操作符并没有什么要讲解的,一句话:你让我不满意,我就换了你!


讲两点要注意的内容吧


1)连续赋值容易使人误解,建议分开赋值.


#include <stdio.h>
int main()
{
  int a = 0, b = 0,c=0;
  a=3,b = 4;
  c = a = b + 1;//连续赋值
  printf("%d %d %d", a, b, c);
  //建议写成如下形式:
  a = b + 1;
  c = a;
  return 0;
}


2)可以使用复合赋值符,简化赋值的代码量.


#include <stdio.h>
int main()
{
  int a = 2, b = 3;
  a += b;//等价于a=a+b
  a -= b;//等价于a=a-b
  a *= b;//等价于a=a*b
  a /= b;//...
  a %= b;
  a >>= b;
  a <<= b;
  a &= b;
  a |= b;
  a ^= b;
  return 0;
}


五、单目操作符


单目运算符;单目操作符的意思是操作数只有一个


!           逻辑反操作
-           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
(类型)       强制类型转换


(1) ‘!’ (逻辑反操作):


将逻辑结果取反,即真的变为假的,假的变为真的.


在c语言中,逻辑假用0表示,非0位真.


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


(2)‘&’ (取地址操作符)


‘&’ (取地址操作符):用于得到变量,数组等的地址.


在C语言中,变量,常量字符串,数组,结构体包括指针等在内存中都是有地址的,需要在内存中分配一块空间来存储这些值,而内存的编号就是内存地址.


但是字面常量(如常数 6)在内存中是没有地址的,因为它本身并不需要在保存下来.



(3)sizeof()操作符与数组的联系


sizeof()用于计算操作数所占空间大小,单位是字节,可以以类型、指针、数组和函数等作为参数。


返回值类型为unsigned int


 #include <stdio.h>
void test1(int arr[])
{
  printf("%d\n", sizeof(arr));
}
void test2(char arr[])
{
  printf("%d\n", sizeof(arr));
}
void test3(float arr[])
{
  printf("%d\n", sizeof(arr));
}
void test4(double arr[])
{
  printf("%d\n", sizeof(arr));
}
int main()
{
  int arr1[10] = { 0 };
  char arr2[10] = { 0 };
  float arr3[10] = { 0 };
  double arr4[10] = { 0 };
  printf("%d\n", sizeof(arr1));
  printf("%d\n", sizeof(arr2));
  printf("%d\n", sizeof(arr3));
  printf("%d\n", sizeof(arr4));
  test1(arr1);
  test2(arr2);
  test3(arr3);
  test4(arr4);
  return 0;
}


结果分析:


我们知道,在数据类型篇已经了解c语言中各数据类型占用多少字节.


所以当sizeof(数组名)操作符在计算不同类型的数组的时候.得到的结果不同,为相应数组中元素总和所占用的字节数.


当我们在数组传参时,传的是数组首元素的地址,而计算地址的大小只有两种结果


32位机器是4字节
64位机器是8字节


运行结果:


40
10
40
80
8
8
8
8


&数组名:这里的数组名表示的是整个数组,即这里取的是整个数组的地址


#include <stdio.h>
int main()
{
  int arr[10] = { 0 };
  printf("&arr=%p\n",&arr) ;
  printf("&arr+1=%p\n", & arr + 1); 
  printf("arr=%p\n", arr);
  printf("arr+1= %p\n", arr + 1);
  return 0;
}



细节来了:


#include <stdio.h>
int main()
{
  char a = 2;
  int b = 3;
  printf("%d\n", sizeof(a = b + 3));
  printf("%d\n", a);
  return 0;
}


运行结果:


1
2


结果分析,sizeof()操作符括号里面的表达式是不进行计算的.所以a=b+3是没有执行的.这是因为sizeof()操作符在编译过程中就已经完成了,而计算需要在运行过程中完成,当运行时,这里已经是sizeof(a)的结果2了.并没有计算.



总结:


数组名一般表示的是数组首元素的地址,但有两个情况是例外的!


1.sizeof(数组名)——这里数组名表示的是整个数组,用于计算整个数组所占空间的大小


2.&数组名-----这里的数组名表示的是整个数组,即这里取的是整个数组的地址数组+1:


1.数组的地址----以整个数组的大小为整体,+1就是跳过整个数组


2.数组首元素的地址-----数组第一个元素的地址,+1就是下一个元素的地址


数组传参传的是数组首元素的地址----计算地址的大小,32位机器是4,64位机器是8


(4)’ ~ ’ (按位取反操作符)


顾名思义,就是将操作数的二进制位按位取反.


例如:


#include <stdio.h>
int main()
{
  int a = 7;
  printf("%d", ~7);
  return 0;
}



(5)前置++和后置++操作符


前置++:操作数先自增(+1),后再被使用.


后置++:操作数先被使用,后自增(+1).


🌰上栗子


#include <stdio.h>
int main()
{
  int a = 5, c = 0;
  //前置++
  c = ++a;//先a自增1使得a的值变为6,然后再被赋值到c.
  printf("%d\n", c);//6
  printf("%d\n", a);//6
  //后置++
  a = 5, c = 0;
  c = a++;//先使a被赋值到c,此时a=5,赋值完成后,a再自增1,变为6.
  printf("%d\n", c);//5
  printf("%d\n", a);//6
  return 0;
}


试着看两段代码练练手吧!


代码1:


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


代码2:


#include <stdio.h>
int main()
{
  int i = 0;
  while (++i < 5)
  {
    printf("%d ", i);
  }
  return 0;
}
目录
相关文章
|
25天前
|
存储 网络协议 C语言
【C语言】位操作符详解 - 《开心消消乐》
位操作符用于在位级别上进行操作。C语言提供了一组位操作符,允许你直接操作整数类型的二进制表示。这些操作符可以有效地处理标志、掩码、位字段等低级编程任务。
71 8
|
25天前
|
C语言
【C语言】逻辑操作符详解 - 《真假美猴王 ! 》
C语言中有三种主要的逻辑运算符:逻辑与(`&&`)、逻辑或(`||`)和逻辑非(`!`)。这些运算符用于执行布尔逻辑运算。
63 7
|
4月前
|
存储 C语言 索引
【C语言篇】操作符详解(下篇)
如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。
88 0
|
4月前
|
程序员 编译器 C语言
【C语言篇】操作符详解(上篇)
这是合法表达式,不会报错,但是通常达不到想要的结果, 即不是保证变量 j 的值在 i 和 k 之间。因为关系运算符是从左到右计算,所以实际执⾏的是下⾯的表达式。
304 0
|
2月前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
51 10
|
2月前
|
存储 编译器 C语言
【C语言】简单介绍进制和操作符
【C语言】简单介绍进制和操作符
198 1
|
2月前
|
存储 编译器 C语言
初识C语言5——操作符详解
初识C语言5——操作符详解
191 0
|
4月前
|
C语言
C语言操作符(补充+面试)
C语言操作符(补充+面试)
48 6
|
4月前
|
存储 编译器 C语言
十一:《初学C语言》— 操作符详解(上)
【8月更文挑战第12天】本篇文章讲解了二进制与非二进制的转换;原码反码和补码;移位操作符及位操作符,并附上多个教学代码及代码练习示例
64 0
十一:《初学C语言》—  操作符详解(上)
|
5月前
|
C语言
五:《初学C语言》— 操作符
本篇文章主要讲解了关系操作符和逻辑操作符并附上了多个代码示例
47 1
五:《初学C语言》—  操作符