【c语言】操作符详解

1,算术操作符+- * / %

其中+ - * /适用于整数或浮点数,%必须是两个整数,不然会报错的。

小数除法只有表达式中至少有一个浮点数才行

2,移位操作符>> <<

操作数只能是整形的二进制,移动补码,移“位”就是移“二进制位”

负数的第一个符号位0正 1负,三者转换关系如下图。正数的原反补相同,没有转换关系

负数的原码反码补码

2.1左移操作符

正数左移

负数左移

我们发现,左移一位就是原来数字的二倍,左移两位就是原来数字的四倍

a=10 , a<<1=20 , a<<2=40

2.2右移操作符,

算术右移还是逻辑右移取决于编译器,大多数编译器是算术右移。

  • 算数右移:右边丢掉,左边补原来的符号位(0正 1负)

  • 逻辑右移:右边丢掉,左边补0(正数的符号位)

-1向右移一位后还是-1,-1的补码存储在内存中,全1内存中存储是二进制的补码,为了方便展示用十六进制全1就是ff ff ff ff,1个十六进制位是四个二进制位。

-1是以补码的形式存储的

-1的右移一位,打印是原码,移动二进制位=移动内存中的补码

-1向右移一位后还是-1

3,位操作符 & | ^

它们的操作数必须是整数,内存中存储的补码,二进制位计算,按“位”与,就是按”二进制位“与。

3的原反补0000…0011

-5的原码1000…0101 反码1111…1010 补码1111…1011

  • 按位与&,有0为0,同1为1。3&-5 结果是0000…0011

  • 按位或 | ,有1为1,同0为0。3|-5结果是1111…1011。因为是负数所以转化为原码是1000…0100,1000 …0101 原码来打印。

  • 按位异或^,相同为0,相异为1。3^-5结果是1111…1000。因为是负数所以转化为原码是1000…0111,1000…1000原码来打印。

按位异或操作符的用法:(缺点是不易阅读)

 //不允许创建临时变量tmp,交换两个整数的内容
int main()
{
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("%d %d", a, b);

    return 0;
}

4,赋值操作符 += -= *= &= |= ^= >>=

5,单目操作符

5.1逻辑反操作 !

非0真—!—>0是假

0是假—!—>1是真

C99引入布尔类型_Bool,用来表示真假的类型来创建临时变量flag,只有两个取值true,false,本质是0,1,需要引用头文件<stdbool.h>,也可以当作函数的返回类型,函数返回true/false

5.2负值- 正值+

unsigned int 类型角度来看-10的补码直接输出,没有符号位,没有正负之分,无原反补概念,内存中就是他的值

5.3取地址& 解引用*
5.4sizeof
  • sizeof是关键字,自己定义的名字不可以用关键字sizeof,语言已经用了

  • sizeof是操作符,功能上是用来计算变量类型,数组类型的大小,操作符计算可以省略括号sizeof arr可以,sizeof int有时候可以。

  • sizeof不是函数,函数调用后面的括号一定不可以省略

  • sizeof内部表达式不参与计算,sizeof是用类型来计算的

5.5按位取反~

对一个数的二进制位按位取反,包括符号位,我们先把1左移三位得到0000…1000再按位取反即可得到1111…0111 。知道了这个我们就可以不改变其他位,只改变二进制的某一位了。

  • 可不可以把0000…1001某一位改成0?按位与1111…0111,得到0000…0001

  • 可不可以把0000…0001某一位改成1?按位或0000…1000,得到0000…1001

5.6前置后置++--

先自加,再使用

先使用,再自加

5.7强制类型转化
5.8sizeof和数组

6,关系操作符> >= != == < <=

7,逻辑操作符&& ||

只关注真假,是非0还是0,是真还是假,3是真,5是真,10是真,0是假

  • 逻辑与操作符&&左边为假,右边不计算

  • 逻辑或操作符 | | 左边为真,右边不计算

8,条件操作符

(exp1)?exp2:exp3

  • exp1是真,计算exp2作为整个表达式的结果,不计算exp3

  • exp1是假,不计算exp2,计算exp3作为整个表达式的结果

9,逗号表达式

exp1,exp2,exp3,...expN

从左到右执行,整个表达式的结果是最后一个表达式的结果,执行过程中可能会影响最后一个表达式的

结果。

从左到右依次执行

逗号表达式的使用

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

10.1下标引用操作符[]

两个操作数是"数组名"和"下标"缺一不可printf("%d\n",arr[4]);

10.2函数调用操作符()

两个操作数是"函数名"和"参数",至少有一个操作数,因为有时候函数没有参数,调用函数时括号不可以省略。

10.3访问一个结构的成员
  • 内置类型:char,int,short,long,float,double。

  • 自定义类型(=聚合类型):结构体类型,枚举类型,联合体类型。把简单的的类型(有字符串,数组…)多个聚合在一起,形成了复杂的描述形式

  • 结构体.成员名

  • 结构体指针->成员名

//创建好了一个类型,struct Book就是一个类型
struct Book
{
    char name[20];
    int price;
    char author[20];
}b1;
//创建了一个全局变量b1

void Print(struct Book* b2)
{
    printf("%s\n", (*b2).author);//可以
    printf("%s\n", b2->author);//传址调用,操作符访问结构体内部

}

int main()
{
    struct Book b2 = { "the book",20,"rose" };// 创建局部变量b2初始化
    printf("%s,%d", b2.name, b2.price);//用操作符.获取b2里面的信息
    Print(&b2);//不能只传b2过去,必须取地址后才是传址调用
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员婧子的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值