栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言操作符详解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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 
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 
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 
int main()
{
    int a = 3;
    printf("%d",sizeof(a));
    printf("%d",sizeof(int));
    printf("%d",sizeof a );
}

输出结果为

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

#include 
int main()
{
	short s = 5;
	int a = 10;
	printf("%dn",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 
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 
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 

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

    struct book* pa = &a;
    
    printf("%sn", (*pa).name);
    printf("%sn", (*pa).id);
    printf("%dn", (*pa).price);


    printf("%sn", pa->name);
    printf("%sn", pa->id);
    printf("%dn", pa->price);

}
    

输出结果

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/853831.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号