【C语言】操作符--百科全书

目录

一、操作符的分类

二、 ⼆进制和进制转换

三、 原码、反码、补码

四、 移位操作符

五、位操作符:&、|、^、~

六、单⽬操作符

七、逗号表达式

八、 下标访问[]、函数调⽤()

九、结构体

十、操作符的属性:优先级、结合性

十一、表达式求值


一、操作符的分类

算术操作符: + - * / %
移位操作符: << >>
位操作符: & | ^ `
赋值操作符: = += -= *= /= %= <<= >>= &= |= ^=
单⽬操作符: !、++--&*+-~ sizeof(类型)
关系操作符: > >= < <= == !=
逻辑操作符: && ||
条件操作符: ? :
逗号表达式: ,
下标引⽤: []
函数调⽤()
结构成员访问: . ->

二、 ⼆进制和进制转换

其实我们经常能听到2进制、8进制、10进制、16进制这样的讲法,那是什么意思呢?其实2进制、8进 制、10进制、16进制是数值的不同表⽰形式⽽已。
10进制中满10进1
10进制的数字每⼀位都是0~9的数字组成
  其实⼆进制也是⼀样的
2进制中满2进1
2进制的数字每⼀位都是0~1的数字组成
那么 1101 就是⼆进制的数字了。
2进制转10进制
其实10进制的123表⽰的值是⼀百⼆⼗三,为什么是这个值呢?其实10进制的每⼀位是权重的,10进 制的数字从右向左是个位、⼗位、百位....
如下图:
2进制位1101
权重2^32^22^12^0
权重值8421
求值1*8+1*4+0*2+1*1=13

 2进制1101每一位权重

三、 原码、反码、补码

整数的2进制表⽰⽅法有三种 ,即原码、反码和补码

有符号整数的三种表⽰⽅法均有符号位和数值位两部分 2进制序列中 ,最⾼位的1位是被当做符号  ,剩余的都是数值位。

符号位都是⽤0表⽰“ 正” ,⽤1表⽰“ 负”。

正整数的原、反、补码都相同。

负整数的三种表⽰⽅法各不相同。

原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。 反码:将原码的符号位不变 ,其他位依次按位取反就可以得到反码。 补码:反码+1就得到补码。

反码得到原码也是可以使⽤:取反,+1的操作。

四、 移位操作符

<< 左移操作符

 >> 右移操作符

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

4.1 左移操作符

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

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

4.2 右移操作符

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

1. 逻辑右移:左边⽤0填充 ,右边丢弃

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

 

五、位操作符:&、|、^、~

位操作符有:
& //按位与
| //按位或
^ //按位异或
~ //按位取反

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

 

六、单⽬操作符

单⽬操作符有这些: !、++ -- & * + - ~ sizeof ( 类型 )
单⽬操作符的特点是只有⼀个操作数,在单⽬操作符中只有&和*没有介绍。

七、逗号表达式

1 exp1, exp2, exp3, …expN
逗号表达式,就是⽤逗号隔开的多个表达式
逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。
//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
//代码2
if (a =b + 1, c=a / 2, d > 0)
//代码3
a = get_val();
count_val(a);
while (a > 0)
{
 //业务处理
 a = get_val();
 count_val(a);
}
如果使⽤逗号表达式,改写:
while (a = get_val(), count_val(a), a>0)
{
 //业务处理
}

 

八、 下标访问[]、函数调⽤()

8.1 [ ] 下标引⽤操作符
操作数:⼀个数组名 + ⼀个索引值
int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。
8.2 函数调⽤操作符
接受⼀个或者多个操作数:第⼀个操作数是函数名,剩余的操作数就是传递给函数的参数。
#include <stdio.h>
void test1()
{
 printf("hehe\n");
}
void test2(const char *str)
{
 printf("%s\n", str);
}
int main()
{
 test1(); //这⾥的()就是作为函数调⽤操作符。
 test2("hello bit.");//这⾥的()就是函数调⽤操作符。
 return 0;
}

九、结构体

结构体关键字:struct

结构体是用来描述一个复杂对象的,他里边可以包含多个属性

//创建出一个新类型
//自定义的类型
struct Satudent
{
  char name[20];//名字
  int high;//身高
  int age;//年龄
  float weight;//体重
  char id[16];//学号
};//这里的分号不能省

结构是一些值的集合,称为成员变量,每个成员可以是不同类型的变量,eg:标量;数组;指针;其他结构体。

结构的声明

struct tag
{
   member-list;
}variable;

结构体的变量 的定义和和初始化

#include<stdio.h>
//创建出一个新类型
//自定义的类型
struct Satudent
{
  char name[20];//名字
  int high;//身高
  int age;//年龄
  float weight;//体重
  char id[16];//学号
};s4,s5,s5;//这里的分号不能省
//s4,s5,s6是结构体变量(全局的)
struct Student s7;//全局的

int main()
{
  struct Student s1={"张三",20,180,75.5f,“20230901022”};//初始化
  struct Student s2={.age=30,.name="lisi",.weight=80。5f,.high=177,.id="20230101033"};
  
  printf("%s %d %d %.1f %s\n ",s1.name,s1.age ,s1.weight ,s1.id);//打印
//struct Student s3={};
//s1,s2,s3是三个结构体变量(局部的)
  return 0;
}

 结构体包含一个结构体

结构体成员的直接访问

#include<stdio.h>
struct S
{

 char c;
 int n;
};

struct B
{
  struct S s;
  int* p;
  char arr[10];
  float sc;
};

int main()
{
  struct B b={{'w',99},NULL,"hehe",85.5f};
  printf("%C\n",b.s.c);
  return 0;
}

结构体成员的间接访问--->指针

十、操作符的属性:优先级、结合性

这两个属性决定表达式求值的先后计算顺序。

int main()
{
  3+4*5;

  return 0;
}

结合性

如果两个运算符优先级相同,优先级没有办法确定计算哪个了,这时候就看结合性,则根据运算符是左结合,还是右结合,决定执行顺序。大部分运算符是左结合(从左到又执行),少数运算符是右结合(从右到左执行),eg:赋值运算符(=

由于圆括号的优先级最高,可以使用它改变其他运算符的优先级

 下表列出C运算符的优先级和结合性,运算符从上到下降序列出

优先级运算符描述结合性
1

++ --

( )

[ ]

.

->

(type){;ist}

后缀自增与自减

函数调用

数组下标

结构体与联合体成员访问

结构体与联合体成员通过指针访问

复合字面量

从左到右
2

++ --

+ -

!~

(type)

*

&

sizeof

_Alignof

前缀自增与自减

一元加与减

逻辑非与逐位非

转型

间接(解引用)

取址

取大小

对齐要求

从右到左
3* / %乘法、除法以及余数从左到右
4+ -加法、减法
5<< >>逻辑左移及右移
6

< <=

> >=

分别为<与<=的关系运算符

分别为>与>=的关系运算符

7== !=分别为=与≠关系
8&逐位与
9^逐位异或(排除成)
10|逐位或(包含成)
11&&逻辑与
12||逻辑或
13?:三元条件从右到左
14

=

+=  -=

*=  /=  %=

<<=  >>=

&=  ^=  |=

简单赋值

以和及差赋值

以积、商及余数赋值

以逐位左移及右移赋值

以逐位与、异或及或赋值

15逗号从左到右

参考:C语言参考手册

十一、表达式求值

整型提升

C语言中整型算术运算总是至少以缺省整型的精度来进行的。

为获得这个精度,表达式中的字符和短型操作数在使用之前被转换为普通整型

int main()
{
  char a=3;//char --signed char
  //00000000/00000000/00000000/00000011
  //00000011 -a
  char b=127;
  //00000000/00000000/00000000/01111111
  //01111111 -b
  char c=a+b;
  //00000000/00000000/00000000/00000011
  //00000000/00000000/00000000/01111111
  //00000000/00000000/00000000/10000010
  //10000010 - c
  //
  //%d - 以10进制的形式打印有符号的整数
  //11111111/11111111/11111111/01000010--C提升后的结果
  //10000000/00000000/00000000/01111101
  //10000000/00000000/00000000/01111110--源码
  printf("%d\n",c);

  return 0;
}

意义:

 如何整体提升:

1.有符号整数提升 是 按照变量的数据类型的符号位来提升的

2.无符号位整数提升,高位补0

 算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换

long double
double
float
unsigned long int
long int 
unsigned int
int

 如果某个操作数的类型在上面这个列表中排名靠后,那么首先要转化为另一个操作数的类型后执行运算。

问题表达式解析

//表达式的求值部分由操作符的优先级决定
//表达式1
a*b + c*d + e*f
#include<stdio.h>
int main()
{
  int i = 1;
  int ret = (++i) + (++i) + (++i);
  printf("%d\n",ret);
  printf("%d\n",i);
  return 0;
}

  • 39
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值