操作符的继续讨论

赋值操作符
这种操作符是c语言比较好用的一种操作符,其功能也比较简单,所以这儿不做详细的解释
复合赋值操作符
这种操作符的其实就是c语言中赋值操作符的一种简化的写法.
比如x=x+1
其实与x+=1是完全等价的
但是上面的可读性明显是大于下面的可读性的
单目操作符
! 表示的是逻辑反操作注意此处的逻辑操作符与前面的按位操作符的区别,逻辑操作符的结果就两种假或者真

  • 表示的不是减法,**-**表示的是负值
    
  • 表示的不是加法,**+**表示的是正值
    

~ 表示的是二进制按位取反,一定要区分与前面的**!**的区别
– 前置,以及后置有着不同的意思,一定要进行区分
++ 前置与后置也有着不同的意思,一定要进行区分

  • 间接访问操作符(解引用操作符)
    

对 ! ~的区分
!:表示的是逻辑取反,那么它的结果只有两个,真或者假,c语言中将0表示假,非0表示真
~:表示的是按照二进制位进行取反,先将一个数转化为二进制,然后对每一位进行取反,然后在进行输出
我们先来尝试一下二进制的按位取反
#include<stdio.h>
#include<stdlib.h>
int main()
{
//我们定义一个十六进制的是数x,0x0表示了十六进制的数0
unsigned int x = 0x0;
//在此处我们尝试一下按位取反~
x = ~x;
//然后我们按照十六进制进行输出
printf("%x\n", x);
system(“pause”);

}
我们可以看到输出的结果为
在这里插入图片描述
我们对代码进行分析可以得到
首先x的初值是十六进制的0,它对应的也是十进制的0,然后我们对它进行按位取反,得到的每一位上就由0变为了1,就是32个1,然后按照十六进制输出,显示的就是8个f,每个f表示4个1
然后我们来看一下逻辑取反
#include<stdio.h>
#include<stdlib.h>
int main()
{
//我们定义一个十六进制的是数x,0x0表示了十六进制的数0
unsigned int x = 0x0;
x = !x;
printf("%d\n", x);
system(“pause”);

}
输出的结果为
在这里插入图片描述
我们来对代码以及运行结果进行分析
首先我们输入的值0x0为一个十六进制的数字,它表示的也是十进制的0,由于逻辑取反的结果为0或者1,因为这个值本事为0,那么逻辑取反之后的值就为1
根据上面的情况,让我们继续区分& 与 &&
与上面的类似&表示的是按位与,而&&表示的是逻辑与,至于他们的区别,我们来看下面的一段代码
&
#include<stdio.h>
#include<stdlib.h>
int main()
{
int x = 0x1;
//表示的是01
int y = 0x2;
//表示的是10
printf("%x\n",x&y);
system(“pause”);
return 0;

}
输出结果如下图所示
在这里插入图片描述
0x1------------>01
0x2------------->10
根据按位与运算的规律有0为0,全1为1
可以得到的结果为0
&&(逻辑与)
输出的结果如下
在这里插入图片描述
因为逻辑运算的结果就两种假或者真,因为0x1表示的是1,而0x2表示的是2,根据逻辑运算中0位假,非0位真,所以,这个的运算结果就为真,即为1
| || 它的运算结果也是相同的道理
注意
sizeof也是一个单目运算符
但是关于sizeof的运算规律,我们需要注意格式的书写
比如写为printf("%d",sizeof(a));
或者写为printf("%d"sizeof(int));
这两种格式都是可以的
但是以下这两种格式是错误的,当使用以下写法时,编译器就会报错
printf("%d",sizeof a);
printf("%d",sizeof int);
这两种写法是坚决不允许的
前置运算与后置运算
x++与++x在不进行赋值运算时是没有什么区别的,但是当进行赋值运算时就需要注意
int a=x++;表示的是先对a进行赋值,然后再对x进行加1的运算
int a=++x;先对x进行加1运算,然后再将这个值赋值给a
其实上述的内容并不能体现前置运算与后置运算的具体特点,但是在for循环中,上述的表述可能更为明确
让我们来看一个"有趣的代码"
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d", ret);
system(“pause”);
return 0;
}
在这里插入图片描述
我们可以看到输出的值为12,为什么呐?就和上面说描述的一样 ++i先执行的是++,所以程序先执行了三次++,这样i的值就变为了4,然后再让3个i的值相加,得到的结果就为12
但是相同的代码,在linux下执行的结果为10
那么那种结果是正确的呐?
其实,两种结果都是不正确的,因为在不同的编译器中,程序执行的顺序是不相同的,所以计算的结果是不相同,但是我们需要注意这两种结果我们都称之为未定义行为,所以说这种形式的代码以后还是要尽量的少写.
关系运算符

=
<=

!=
表示都为关系运算符
注意区分关系运算符中的"=“和”==“的区别,在写程序的时候不要混用
在有的编译器中,赋值运算符还可以写为<>
我们来看一道有趣的360面试题
#include<stdio.h>
#include<stdlib.h>
int main()
{
int i = 0, a = 0, b = 1, c = 2, d = 4;
//短路操作
//当执行逻辑与运算时,当它发现a的值已经为0,根据逻辑或的运算规矩,这个值就为0,那么它就不会执行后面的++b和d++了
//同理,当执行逻辑或运算时,当第一个的值为1时,它就不会执行后面的内容了
i = a++&&++b&&d++;
printf(“a=%d b=%d d=%d”, a, b, d);
system(“pause”);
return 0;
}
在这里插入图片描述
上述的代码完全体现了短路操作这一特性,具体的功能我写到了注释这种.
条件操作符(三目运算符)
三目运算符的标准格式为
exp1?exp2:exp3
其实就是if else语句的另一种写法
#include<stdio.h>
#include<stdlib.h>
int main()
{
int a = 1;
int b = 2;
a > b ? printf(“较大的数字为a”) : printf(“较大的数字为b”);
system(“pause”);
return 0;
}
逗号表达式
格式:exp1,exp2,exp3,expN
逗号表达式表示的就是由逗号隔开的多个表达式
逗号表达式,从左向右依次执行,整个表达式的结果就是最后一个表达式的结果
看下面一段代码
int a=1;
int b=2;
int c=(a>b,a=b+10,a,b=a+1);
c的值为多少?
根据逗号表达式的运算规律,从左向右依次计算,得到的结果就为13
这个代码相对比较鸡肋,所以以后尽量少的使用
下标引用
1.[]表示了一个下标引用操作符
操作数:一个数组名+一个索引值
比如:int arr[10]//创建一个数组
arr[9]=10;//实用下标引用操作符
[]的两个操作值都为arr和9
关于数组的越界使用
vs中越界使用数组中的值,编译器是不会报错的,但是会越界调用数组得到的是一个随机值
2.函数的调用操作符
函数的调用操作符包括两部分,一部分是要调用的函数,另一部分是在括号中要传递进入函数的参数
整形提升
#include<stdio.h>
#include<stdlib.h>
int main()
{
//表示11111111
unsigned char a = 255;
//当执行unsigned char 的过程中发生了"整形提升”
//char提升为了int型,变为了32位
//虽然发生了左移和右移,但是还是8个1
unsigned char b = (a << 1) >> 1;
printf(“b=%x\n”, b);
system(“pause”);
return 0;

}
在这里插入图片描述
整形提升的意义
表达式的整形运算要在cpu相应的运算器件中执行,cpu内整形运算器的操作数的字节长度一般就是int的字节长度,同时也是cpu通用寄存器的长度
因此,即使两个char类型进行相加,在cpu执行时实际上也是要先转换为cpu内整形操作数的标准长度
因为通用cpu是很难执行两个8比特字节的相加运算,所以,表达式中各种可能小于int的数,会先转换为int或者unsiged int 才能送入cpu中去执行运算
对于上面这几段话的理解:还是因为计算机内部运算的原因,cpu处理数据的过程是按照int的大小来进行处理的,所以对于char类型的变量会先转化为int型或者unsigned int型来进行运算
,所以比int短的数据类型,都会整形提升为int型来方便cpu对数据进行处理
关于整形提升的规律(负数与正数是不同的)
负数的整形提升
char c1=-1;
变量c1的二进制补码有8个比特位
11111111
因为char为有符号的char,而不是无符号的char(unsigned char)
所以整形提升的时候提升的是符号位,就是提升1
11111111111111111111111111111111(这是32个1)
正数的整形提升
char c2=1;
变量c的二进制位(补码)中只有8个比特位(这是由数据类型决定的)
00000001
因为char为有符号的char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果为
0000000000000000000000000000001
无符号位,整形提升时,高位补0
//我们来看一个整形提升的实际例子
#include<stdio.h>
#include<stdlib.h>
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
{
printf(“a”);
}
if (b == 0xb600)
{
printf(“b”);
}
if (c == 0xb6000000)
{
printf(“c”);
}
system(“pause”);
return 0;
}
我们可以看到输出的结果为
在这里插入图片描述
为什么会出现这样的结果那我们对代码进行分析
首先我们可以判断的是abc都为负数,a为char型,b为short型,而c为int型,a,b进行了整形提升之后,a与b的值都变为负数,所以前两个表达式的值为假,而c的数据类型本身就为int型,所以不需要进行整形提升,所以第三个表达式是成立的,所以输出的结果为c
算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非一个操作数转换为另一个操作数的类型,否则操作就无法进行,下面的层次体系称为寻常算数转换
long double
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面的列表中的排名比较低,那么首先要转换为另一个操作数的类型之后再进行运算
警告
算数的转换要合理,不然会存在一些潜在的问题
float f=3.14;
int num=f;//这种情况下的隐式转换,会使得数据的精度丢失
未定义行为
当你写的代码中存在歧义,并且在不同的操作环境,以及不同的语意之下的结果是不相同的的,这样的行为称之为未定义行为

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值