C语言操作符详解

c语言操作符详解

c语言的操作符有以下几大类

  1. 算数操作符
  2. 位移操作符
  3. 位操作符
  4. 赋值操作符
  5. 单目操作符
  6. 关系操作符
  7. 逻辑操作符
  8. 条件操作符
  9. 逗号表达式
  10. 下标应用,函数调用和结构成员

1.算术操作符

1|  +  -  *  /  %
  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
  2. / 操作符是取商,% 操作符是取余
  3. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。(例如:int a= 3 / 5 ,a结果为0 , 但 int a = 5.0 / 3 或 int a = 5 / 3.0 , a 的结果依然为0。如果想要小数位上有值就要写成double a = 5.0 / 3 或 flout a = 5 / 3.0)
  4. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。

2.位移操作符

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

1| << >>

举个例子

int a = 1;
int b = a<<1;//向左移动一位

打印出来b的结果是2。
其实这里的移位移的是二进制位,例子中的a在内存中的存放是 :
00000000000000000000000000000001
左移一位后得到的b结果为
00000000000000000000000000000010
这里可以看出左移操作符的特点为:左边丢弃,右边补零

再举一个例子

int a = -1;
int b = a>>1//向右移动一位

这里打印出来b的结果还是-1
其实右移操作符有两种右移方法

1.算数右移(正负数都通用)

右边丢弃,左边补原符号位

2.逻辑右移(正数)

右边丢弃,左边补零

所以上面代码a在内存中的存放为:
原码:10000000000000000000000000000001
反码:1111111111111111111111111111111111110
补码:1111111111111111111111111111111111111
所以右移一位,左边补符号位,右边丢弃,得到的结果为
补码:1111111111111111111111111111111111111
所以-1右移一位得到的结果b还是-1
注意a向右移动,是把a向右移动之后的值赋给了b,这里的a没有发生改变它的值还是之前a赋的值

补充

正数与负数在内存中的存放方式都是以补码的方式存放(正数的原码,反码,补码都相同)
负数的符号位就是在二进制数列的第一位写1
正数的符号位是0
整数二进制的表达形式其实有三种
原码:直接根据数值写出二进制序列就是原码
反码:原码的符号位不变,其它的按位取反就是反码
补码:反码+1,就是补码

3.位操作符

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

注:他们的操作数必须是整数。
举例说明:

&按(二进制)位与
int a = 3;
int b = 5;
// & - 按(二进制)位与
int c = a & b;

a 的二进制为 00000000000000000000000000000011
b 的二进制为 00000000000000000000000000000101
c 的二进制为 00000000000000000000000000000001
如果a,b对应二进制位相同那么输出 c 的二进制对应位不变,如果a,b二进制位不同那么输出 c 的对应二进制位为0。所以 c 的值为1

| 按(二进制)位或

如果 int c = a | b;
对应的二进制位只要有1则输出为1,只有两个都为0结果才为0;故结果为00000000000000000000000000000111;故c的值为7

^ 按(二进制)位异或

如果 int c = a ^ b;
对应的二进制位相同则为0 ,相异则为1;故结果为00000000000000000000000000000110;故c的值为6
可是这个操作符到底有什么用呢???
先来看一道题:
创建两个变量int a = 3; int b = 5。要求不能创建一个新的变量,并且交换他们两个的值

这里你又想到了什么方法呢?
先用一个以往的方法

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

得到的结果在这里插入图片描述
但是这样写有一个缺陷,如果a赋一个很大的值,b赋一个很大的值,a+b可能会超出int整形表示的最大值
所以我们使用刚刚学到的那种方法

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

得到的结果
在这里插入图片描述
这里的b可以写成 b = a ^ b ^ b ;两个相同的数异或一定为0,那b就等于a ^ 0,并且0^任何数都等于它本身,那b就等于a的值了

4.赋值操作符

=   +=   -=  *=   /=   >>=   <<=    %=    &=   |=    ^=

复合赋值:

int x = 10; 
x = x+10;
x += 10;//复合赋值
//其他运算符一样的道理。这样写更加简洁。

需要注意的是: ‘=’ 一个等号才叫赋值,两个等号叫判断相等

5.单目操作符

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

来看两张图来理解
在这里插入图片描述
在这里插入图片描述
可以看出这里的 !逻辑取反意思就是把真变假,把假变真

sizeof 计算所占空间的大小

可以写成

#include <stdio.h>
int main()
{
    int a = 3;
    printf("%d",sizeof(a));
    printf("%d",sizeof(int));
    printf("%d",sizeof a );
}

输出结果为

这里的 printf(“%d\n”,sizeof a ) a可以不加括号说明 sizeof 不是函数,是一个操作符
再来举一个例子:

#include <stdio.h>
int main()
{
	short s = 5;
	int a = 10;
	printf("%d\n",sizeof(s = a + 5));
	printf("%d",s);
}

先想一下这道题的答案再看下面的结果
在这里插入图片描述
这里 s = a + 5 是把 a+5 的值赋给了 s 所以 sizeof 输出的结果还是一个短整型 short 所占的的内存,还可以看出 sizeof 括号内的值不参与运算所以下面 s 的输出值没有改变

~ 对一个数的二进制按位取反

例如 -1 在二进制中的存放
原码:10000000000000000000000000000001
反码:11111111111111111111111111111110
补码:11111111111111111111111111111111
所以 -1 按位取反后为
00000000000000000000000000000000
得到的 ~-1 的结果为 0

- - ++

举个例子

int a = 3;
int b = 5;
int c = --a;
int d = b++;
printf("%d %d %d %d",a,b,c,d);

输出结果为
在这里插入图片描述
这里的 ++a 是先 运算再赋值;–a是先 赋值再运算

&取地址操作符与 * 间接访问操作符(解引用操作符)

这里看下面的代码就可以很好的理解了
在这里插入图片描述

(类型) 强制类型转换

看图来理解
在这里插入图片描述
这里可以看到在编译时出现的问题,但如果在3.14前加上一个括号来转换类型就不会出现下面的提示了
在这里插入图片描述

6.关系操作符

>
>=
<
<=
!=      用于测试“不相等”
==      用于测试“相等”

这些关系运算符比较简单,,但是我们要注意一些运算符使用时候的陷阱。
1 . = 是赋值,== 是判断相等。
2 . 比较字符串不能使用 == 来判断

7.逻辑操作符

&&          逻辑与
||          逻辑或

他们都是用来判断真假的
&&:(A 和 B都为真,结果才为真,其中一个为假,结果便为假)
|| :(A 和 B其中一个为真,结果就为真,两个都为假,结果才为假)
这里给大家出一道 && 的题:
先自己做完再往下看

#include <stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ && ++b && d++;
    printf("%d %d %d %d",a, b, c, d);
    return 0;
}

结果为:
在这里插入图片描述
这里的 i = a++ && ++b && d++;是先判断a++,但a++是先赋值再运算,这里赋值为 0 了,所以后面的 ++b && d++ 就没有运算
再来一到 || 的题:

#include <stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ || ++b || d++;
    printf("%d %d %d %d", a, b, c, d);
    return 0;
}

结果为:
在这里插入图片描述
这里的i = a++ || ++b || d++;,判断a++为 0 - 假 ,继续执行 ++b ,++b为真,停止运行,所以结果输出为1 3 3 4
总结:若&&运算符左边表达式为假(0),则其右侧表达式不再计算,整个表达式必然为假;若||运算符左边的表达式为真(非0的值)则其右侧表达式不再计算,整个表达式为真

8.条件操作符

exp1 ? exp2 : exp3

这里的意思就是如果exp1成立(为真)就执行exp2,否则执行exp3

9.逗号表达式

exp1, exp2, exp3, …expN

逗号表达式,从左向右依次计算,但是整个表达式的结果是最后一个表达式的结果
举个例子来理解:

int main()
{
	int a = 3;
	int b = 4;
	int c = 0;
	int d = (c = 5, a = b + c, b = c + a);
	printf("%d", d);
}

这道题d的结果为14
在这里插入图片描述
这里需要注意的是前面的表达式虽然不打印,但也要计算,一定要注意不能直接计算最后一个表达式!

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

1. []下标引用操作符

看下面代码来理解
在这里插入图片描述
arr【5】是把数组中第六个元素改变了

2. ( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
举例:

// 函数的定义
int Add(x,y)
{
    return x+y;
}

void text()
{}
int main()
{
    int a = 10;
    int b = 20;
    int ret = Add(a, b);// 这个括号便是叫函数调用操作符;
    text();//即使不传参也要加括号
    return 0;
}
3. 访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名

举例:
假如这里有一本书:书名,书号,价格
创建一个自定义的类型

#include <stdio.h>

struct book
{
    char name[20];
    char id[20];
    int price;
};
int main()
{
    struct book a = { "c语言","c54564546",30 };
    printf("%s\n", a.name);
    printf("%s\n", a.id);
    printf("%d\n", a.price);

    struct book* pa = &a;
    
    printf("%s\n", (*pa).name);
    printf("%s\n", (*pa).id);
    printf("%d\n", (*pa).price);


    printf("%s\n", pa->name);
    printf("%s\n", pa->id);
    printf("%d\n", pa->price);

}
    

输出结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

专科在努力!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值