【按位取反,逻辑操作符,条件操作符,逗号表达式,下标引用,函数调用,结构体】操作符后续+表达式求值(上)

*注:操作符前半部分详解在

https://blog.csdn.net/weixin_71138261/article/details/126054557?spm=1001.2014.3001.5501

 今天的干货满满,第一块专讲操作符后续

此外欢迎大家参考我的git仓库

这个用来写一些平时的代码,很全面,也有三子棋扫雷的完整版

https://gitee.com/littleegg/learn-to-knock-the-code

这个包含作者刷题的答案和心得

https://gitee.com/littleegg/study.c

目录

1.按位取反:~

 2.逻辑操作符

3.条件操作符

4.逗号表达式

5.下标引用,函数调用,结构体

6.表达式求值


1.按位取反:~

功能:整数二进制序列0 1互换

例如

int a = 1;        00000000000000000000000000000001 (32个比特位)

int b =~a;       11111111111111111111111111111110(32个比特位 )  

 (没对齐是数字大小的原因。)

看起来很简单的操作符在实际应用却需要一点脑筋

如果我们要实现

输入

一个整型n和一个整数i(表示从高位开始第几位)

输出

先判断这一位是不是0,如果不是将这一位改成0

例如   输入21 5   输出5 

看代码

#include<stdio.h>
int main()
{
	int n = 0;
	int i = 0;
	scanf("%d%d", &n,&i);
	int c = 1 << (i-1);
	if (!(n & c))
		printf("这一位本来就是0哦\n");
	else
		n &= ~c;
	printf("%d", n);
}


2.逻辑操作符 

 && 逻辑与   等价数学“且‘

|| 逻辑或        等价数学”或“

*注:C语言没有 0<=a<=12  从中间拆开加上&&

看似好掌握其实有一个易错点

例如下面的代码结果是多少呢

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

   答案:0 1 2 3 4

首先明确a++ 是先把a的值带入计算 在计算完a+=1

所以在一串&&的计算式子里,第一个表达式为假,后面的语句都不执行,并且返回0(假)

因此只有a+=1 其他值都不变  i返回0

如果把a=1 结果变成多少?

答案: 1 1 3 3 5

所有表达式都为真,全真则真,i返回1,其他按照前后置操作符操作(方法在文章开头的连接)

如果a不变 换成||呢

答案: 1 1 3 3 5

全假才假,只有一个表达式为假是说明不了问题的,所有语句照常执行,i返回1


3.条件操作符:exp1?exp2:exp3

又名:三目操作符(几目看有几个操作数,这里三个表达式为他的三个操作数) 

 功能:exp1成真  执行 exp2,否则执行 exp3

*注:不推荐两个三目操作符套用,可读性会降低

例如下面的代码可以用三目操作符优化 

#include<stdio.h>
int main()
{
   int n=0;
   scanf("%d",&n);
   if(n>5)
    n++;
   else
    n--;
  printf("%d",n);
}

 优化为   

#include<stdio.h>
int main()
{
    int n = 0;
    scanf("%d", &n);
    if (n > 5?n++:n--)
    printf("%d", n);
}

 
4.逗号表达式 

 使用:从左到右依次计算,最后一个表达式的结果为整个逗号表达式的结果

*注:详解在文章开头的连接


5.下标引用[],函数调用(),结构体

[] 两个操作数     数组名 和 索引值

例如 int arr[22]

[]的操作数为 arr 和 22

函数调用操作符()操作数看情况而定  函数名和括号里面的参数

例如 test(c)

函数调用操作符 ()的操作数有两个:test   和   c

*注 :反复强调“函数调用操作符 ()”因为括号在表达式中还有别的用处,比如突出优先级

访问结构体成员有两种方法

结构体.数组名  (有个点.)

结构体指针->成员名

 例如

#include<stdio.h>
struct Dan
{
	char name[20];
	int age = 0;
	char type[20];
};
int main()
{
	struct Dan dada = {"dada",19,"leader"};
    struct Dan* pStr = &dada;
printf("%s %d %s", pStr->name, dada.age, pStr->type);
}

不要漏掉结构体后面}的;分号,这一点和枚举关键字一样


到此操作符讲解结束

6.表达式求值 

 表达式求值顺序的一部分是由操作符的优先级和结合性决定

有些表达式的操作数在求值过程中可能需要转化为其他类型

 6.1 隐式类型转换

C的整型算术运算总是默认整型类型的精度来进行

为了获取这个精度,

表达式中的字符和短整型操作数在使用之前被转化为普通整型

这种转换叫做整形提升

*注:可能上述术语太过晦涩 ,我的理解是

整型提升就是  如果一个整型是 short 或者 char 类型,

首先需要写出两个整型的补码         (源反补的转换在文章开头的链接)

然后从低位数 char就是8个比特位  short是16个比特位  截断

在进行计算先把所有数 整形提升 后 运算

最后的结果根据类型选择要不要截断(short和char要)

然后把二进制序列再 整形提升(如果上一步截断了) 然后写成原码输出

整型提升的方法:截断之后高位补充符号位,最后要变成int再高位补0 

看代码 

#include<stdio.h>
int main()
{
	char a= 126;
	char b = 5;
	char c = a + b;
	printf("%d", c);
}

126的二进制序列是

00000000000000000000000001111110

存储在内存里三码相同

截断之后  char只能存放8个比特位  01111110

5的序列是

000000000000000000000000000000101

截断之后 00000101

整形提升(高位补充符号位)之后相加得到

c= a + b=00000000000000000000000010000011

截断之后为10000011

在C语言以整型类型精度进行 所以高位补齐为符号位1

结果是11111111111111111111111110000011

这是补码

-1为

11111111111111111111111110000010

符号位不变 其他位按位取反为

10000000000000000000000001111101

转换成十进制为-125

再比如 

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");
}

 a 和 b 都需要进行整型提升

但是c已经是int不需要整型提升

a b整形提升之后变成了负数  不满足两个if的条件

所以最后结果是打印 c

6.2  算数转换

如果两个不同类型的操作数运算  需要转换类型

首先无论何时char 和 short 都换成int

 其次,long double > double > float > unsigned long int > long int > unsigned int > int

 例如   float+int  这则需要把int转换成float再计算

否则会有精度丢失

6.3操作符的属性

表达式求值有三个影响因素

1.操作符优先性

2.操作符结合性

3.是否控制求值顺序

相邻两个操作符先执行哪个? 根据先1.后2.

优先性的表格在网上很容易搜到 这里就不贴了

*注:不要写问题表达式(无法通过1.2.3.确定唯一计算路径的式子)

至此 表达式求值上篇也告一段落 

创作不易,感谢观看 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值