操作符详解

1.操作符分类

算术操作符

移位操作符

位操作符

赋值操作符

单目操作符

关系操作符

逻辑操作符

条件操作符

逗号表达式

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

2.算术操作符

+、-、*、/、%

  1. 对于/操作符。如果两个操作数都为整数,执行整数除法,返回两个数的商,如果任意一个或者两个都是浮点数则执行浮点数乘法,返回两个数相除的值

  1. 对于%操作符,两个操作数只能为整数,返回两个操作数相除的余数

  1. 除了%操作符,其他操作符都可以用于整数浮点数

3.移位操作符

<< 左移位操作符

>>右移位操作符

注意:移位操作符的操作数只能是整数,不要移动负数位,移位操作符的对象是操作数的补码,

左移操作符:操作数的补码左边抛弃,右边补零,其效果相当于让操作数*2

如5和-5

5的补码是00000000000000000000000000000101

5<<1,则变为00000000000000000000000000001010,

而正整数的原码与补码相同,所以5<<1的值就为10

-5的补码是111111111111111111111111111111111011

-5<<1,则变为111111111111111111111111111111110110

可得到原码为10000000000000000000000000001010

右移操作符:1.算术右移:操作数的补码右边丢弃,左边用符号位填充 2.逻辑右移:操作数的补码右边丢弃左边补零

绝大数编译器采用算术右移,操作如上

4.位操作数

按位与:&,按位或| 按位异或^

注意:他们的操作数都为整数

按位与:两个操作数的补码的二进制位一一比较,若都为1则为1,反之为0

按位或:两个操作数的补码的二进制位一一比较,若其中一个为1则为1,反之为0

按位异或,两个操作数的补码的二进制位一一比较,若相同则为0,反之为1

利用按位异或可以交换两个变量大小,如下

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

如果我们想要知道一个整数储存在内存中的二进制1的个数,可以利用&解决代码如下

#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
for(i=0; i<32; i++)
{
if( num & (1 << i) )
count++;
}
printf("二进制中1的个数 = %d\n",count);
return 0;
}

因为整数占四个字节,32个比特位,所以进行32次循环,让1进行32次左右操作,让1分别依次出现在32个位置,因为除了当前位置外的其他位置都为零,其他位置进行&操作一定为0,所以可以判断目标数的当前位置是0还是1,若为0,num & (1 << i)为0,为假,若为1,num & (1 << i)不为0,为真,count增加

举例:5的二进制为000000000000000000000000000000101

只有1<<0 得到 000000000000000000000000000000001

和 1<<2得到 000000000000000000000000000000100

的情况下

num & (1 << i)才为真,因此count为2

5.赋值操作符

=,可以连续使用比如,比如a=x=y+1,从右往左看一一赋值,等同于x=y+1,a=x

复合赋值符:+=、-=、*=、/=、%=、>>=、<<=、^=、&=、|=

6.单目操作符

! 逻辑反操作

- 负值

+ 正值

& 取地址

sizeof 操作数的类型长度

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

-- 前置、后置--

++ 前置、后置++

* 间接访问操作符

(类型)强制类型转换

注意:sizeof可以计算数组大小,但在数组传参时,利用形参计算数组大小,得不到正确数值,因为此时的形参实际上是指针,计算的是指针大小

#include <stdio.h>
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//(4)
}
int main()
{
icnt arr[10] = {0};
char ch[10] = {0};
printf("%d\n", sizeof(arr));//(1)
printf("%d\n", sizeof(ch));//(3)
test1(arr);
test2(ch);
return 0;
}

此时(1)为10*4(2)为10*1,而(2)(4)都是计算指针大小,为4或8

7.关系操作

>、>=、<=、!=、==

注意:相等是两个等号

8.逻辑操作符

&& 逻辑与

||逻辑或

&&:若左右两个表达式都为真,则为真,反之为假

||:若左右两个表达式都为假,则为假,反之为真

若&&左边为假,则后面不进行判断,因为此时整个表达式一定为假

若||左边为真,则后面不进行判断,因为此时整个表达式一定为真

int i = 0,a=0,b=2,c =3,d=4;
i = a++ && ++b && d++;
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;

此时a++先用a的值为0,整个表达式已经确定为假,所以++b与d++不进行计算

此时a=1,b=2,c=3,d=4

9.条件操作符

exp1?exp2:exp3

若exp为真表达式的值为exp2的值,若exp1为假表达式的值为exp3的值

10.逗号表达式

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

逗号表达式在循环中有一个神奇的运用

a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
a = get_val();
count_val(a);
}

若用逗号表达式可以改写成

while (a = get_val(), count_val(a), a>0)
{
//业务处理
}

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

  1. []下标引用操作符

操作数:一个数组名+一个索引值,如下

int arr[10]=0;
arr[1]=8;

这里面arr和1都是操作数

  1. ()函数调用操作符

操作数:函数名+参数(可以没有),如下

#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;
}

这里面test1是不需要参数的函数,test2是需要参数的函数

3.访问一个结构的成员

结构体.成员名

结构体指针->成员名

如下

#include <stdio.h>
struct Stu
{
char name[10];
int age;
char sex[5];
double score;
};
void set_age1(struct Stu stu)
{
stu.age = 18;
}
void set_age2(struct Stu* pStu)
{
pStu->age = 18;//结构成员访问
}
int main()
{
struct Stu stu;
struct Stu* pStu = &stu;//结构成员访问
stu.age = 20;//结构成员访问
set_age1(stu);
pStu->age = 20;//结构成员访问
set_age2(pStu);
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值