文章目录

  • 计算型细节
  • 表达式细节
  • 大家回答对了几道题?欢迎评论
  • 1.现在正式讲解上面所有的题设计到的内容--------表达式求值
    • 1.1隐式类型转换 (整型截断与提升)
      • 1.1.1 第一题讲解
      • 1.1.2 第二题讲解
      • 1.1.3 第三题讲解
    • 1.2算术转换
    • 1.3 操作符属性
      • 1.3.1 什么是优先级?
      • 1.3.2 什么是结合性?
      • 1.3.3 什么是求值顺序?
      • 1.3.4 第四题讲解
      • 1.3.5 第五题讲解
      • 1.3.6 第六题讲解
      • 1.3.7 第七题讲解
  • 总结:

既然题目都说了是小细节,一来就介绍细节多没意思啊,先坑坑大家再详细介绍吧,嘿嘿.直接上7个题吧,看看你能做对几个呢?


计算型细节

①:

#include <stdio.h>
int main()
{char a = 3;char b = 127;char c = a + b;printf("结果是:%d",c);return 0;
}

您想想这个题的答案是多少?先不要看后面的答案哦
答案是 -126, 嘿嘿,是不是答错了呢?先不要着急,继续看下面的题

②:

#include <stdio.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");return 0;
}

您想想这个题的答案是什么呢? 先不要看后面的答案哦
答案是 c,嘿嘿,是不是又回答错误,先不要着急,再看看后面的题

③:

#include <stdio.h>
int main()
{char c = 1;printf("%u\n", sizeof(c));printf("%u\n", sizeof(+c));printf("%u\n", sizeof(-c));return 0;
}

您想想这个题的答案是什么呢? 先不要看后面的答案哦
答案是1 4 4,嘿嘿,是不是又回答错误,先不要着急,再看看后面的题

表达式细节

①:

#include <stdio.h>
int main()
{int c = 3;int ret = c + --c;printf("%d",ret);  return 0;
}

您想想这个题的答案是什么呢? 先不要看后面的答案哦
答案是 5 或者 4,是不确定的,嘿嘿,是不是又回答错误,先不要着急,再看看后
面的题

②:

int main()
{int i = 10;i = i-- - --i * ( i = -3 ) * i++ + ++i;printf("i = %d\n", i);return 0;
}

您想想这个题的答案是什么呢? 先不要看后面的答案哦
答案有很多个,在不同的编译器结果不同,也就是说还是不能确定结果,嘿嘿,是不是仍然回答错误了,先不要着急,再看看后面的题

③:

#include <stdio.h>
int fun()
{static int count = 1;return ++count;
}int main()
{int answer;answer = fun() - fun() * fun();printf( "%d\n", answer);//输出多少?return 0;
}

您想想这个题的答案是什么呢? 先不要看后面的答案哦
答案是 不同编译器不同结果 ,嘿嘿,是不是又回答错误,先不要着急,再看看后面的题

④:

#include <stdio.h>
int main()
{int i = 1;int ret = (++i) + (++i) + (++i);printf("%d\n", ret);printf("%d\n", i);return 0;
}

这是最后一个题了,你目前答对了几道了呢??请在评论回答试试.嘿嘿
这个题的答案是 不同编译器不同结果

大家回答对了几道题?欢迎评论

1.现在正式讲解上面所有的题设计到的内容--------表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。


1.1隐式类型转换 (整型截断与提升)

什么是隐式类型转换,整型提升,整型截断?

C的整型算术运算总是至少以满足整型类型的精度来进行的。
为了获得这个精度,表达式中若有charshort类型必须在使用之前转换称为整型,这个过程叫做 整型提升
.
一个较大数据类型存储在较小数据类型中的过程叫做整型截断,比如整型a = 500,但是a把他的值放到了字符型b中,b不能完全存放a,就会发生整型截断
.
而这个转换行为叫做 隐式类型转换

1.1.1 第一题讲解

#include <stdio.h>
int main()
{char a = 3;char b = 127;char c = a + b;printf("结果是:%d",c);return 0;
}

我们知道计算机中一切都是操作的补码.所以这里也是一样,(不明白原码补码反码的自己去百度下哦).
其中 正数的 原码 反码 补码 一模一样
… …负数的 补码是反码加一,反码是原码除了符号位所有位都按位取反

a只有1个字节,他的补码是00000011(二进制)
b只有1个字节,他的补码是01111111(二进制)
a加b,进行了算术操作,需要提升到4个字节.而整型提升有两种方式

  • 算术提升:在最前面补符号位数字,直到32位
  • 逻辑提升:无论什么都只补0,直到32位
    大多数计算器都是进行的算术提升,这里便讲解算术提升.

a算术提升后就是00000000000000000000000000000011
b算术提升后就是00000000000000000000000001111111
a+b的结果是------00000000000000000000000010000010
存进c里面,c又只有1个字节,所以发生整型截断,只存取最后8位
10000010
此时c存取的是补码,且c是有符号型,记住了!!,打印显示时候会还原位原码的,该补码对应的数字就是 -126

下面有张字符类型原码补码反码的对应理解图


所以有符号的范围是 [-128,127]
无符号的范围是[0,255]

变成圆圈更好理解,自己按照有无符号对应去找就行.





1.1.2 第二题讲解

#include <stdio.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");return 0;
}

0xb6的二进制是 00000000000000000000000010110110
存进去a中,发生截断,得到1011 0110
0xb600的二进制是00000000 00000000 10110110 00000000
存进去b中发生截断,得到10110110 00000000
0xb600000010110110 00000000 00000000 00000000
存进去c中刚刚好.

a此时存的是补码,a又与0xb6比较,参与了运算,所以又整型提升为
11111111 11111111 11111111 10110110,

  • 整型提升后的数字与0xb6的二进制不一样,所以不等.

b此时存的是补码,b又与0xb600比较,参与了运算,所以又整型提升为
11111111 11111111 10110110 00000000

  • 整型提升后的数字与0xb600的二进制不一样,所以不等

c此时存的是10110110 00000000 00000000 00000000,注意哦~,有人可能会问0xb6000000是正数啊,不!!!!!,字面常量只要不带符号就是默认int类型.所以此时0xb6000000的整数值是超过int的,就会认为它此时的二进制是负数的补码.所以c与0xb6000000是相等的.



1.1.3 第三题讲解

#include <stdio.h>
int main()
{char c = 1;printf("%u\n", sizeof(c));printf("%u\n", sizeof(+c));printf("%u\n", sizeof(-c));return 0;
}

sizeof 测量的是类型属性的值.
c的类型是 char,只有一个字节,所以答案是1
+c,+是单目操作符,与c在一起发生了整型提升,变成了int,所以是4个字节,答案是 4
-c,同样的道理,仍然是4

1.2算术转换

上面我们说到,如果操作数大小 小于int,会发生整型提升,但是如果都是大于等于int大小的类型参与算术运算呢?? 这里就会涉及到 算术转换.
什么是算术转换呢? 比如下面的例子:

#include <stdio.h>
int main()
{int a = -127;unsigned int b =  129;if(a > b){printf("a会大于b");}return 0;
}

结果会打印 a会大于b
因为这就是算术转换,即还是需要满足同类型运算,unsigned int 比int 高,所以a的值会默认是 无符号的,a就会比b大.

算术提升方向:


1.3 操作符属性

复杂表达式的求值有三个影响的因素。

  1. 操作符的优先级
  2. 操作符的结合性
  3. 是否控制求值顺序。

1.3.1 什么是优先级?

就是决定先计算什么.比如d = a + b*c. 因为*的优先级高于+,所以,先算b*c,再算+

1.3.2 什么是结合性?

就是同样优先级,就决定从哪个方向计算.比如d = a * b * c ,因为连续的*,优先级已经没有用了,所以此时就是结合性,*的结合性是从左到右.也就是说先计算a*b 然后计算*c.

1.3.3 什么是求值顺序?

就是只计算哪边.c语言的操作符具有求值顺序的只有寥寥几个,比如||, && , !
求值顺序到底什么意思呢?
比如a等于0,b等于2,c等于3,d = a && b && c,d的值最后是0,但是在运算时候只到a就完结了,因为&&是只要碰到假就是假,后面的真假已经无关,a为0,是假,所以后面不用再管.这就是求值顺序.

下面有两个关于求值顺序的小练习:

#include <stdio.h>
int main()
{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;
}

答案是 1 2 3 4.理由: a是后置++,先使用a=0的值,一开始就遇到假了,后面不再执行.但是a还是增加了的,因为后置加加是 先使用再加加

#include <stdio.h>
int main()
{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;
}

答案:1 2 3 4,前置++,即先加加,a成了1,因为||一遇到真就结束,不再管后面真假.所以只有a变化了.


这里有张操作符属性的表:


其中优先级从上往下逐渐降低

1.3.4 第四题讲解

#include <stdio.h>
int main()
{int c = 3;int ret = c + --c;printf("%d",ret);  return 0;
}

ret = c + --c中有两个操作符号,先看优先级,--的优先级高于+,所以决定了先算–c,但是+号左边的c是什么时候准备的呢? 我们知道,c语言是编译性语言,在代码写好以后是需要先进行编译为机器语言,然后执行的.那么在编译时候,+号左边的值是在--c之前就已经编译好了呢,还是--c之后编译好了呢?这是不确定的.

  • 在vs编译器下答案是 4,他是在--c之后准备好了c
  • 在gcc编译器下答案是 5,他是在--c之前准备好了c

所以: 这是问题代码,我们以后不要写这样的垃圾代码.

1.3.5 第五题讲解

int main()
{int i = 10;i = i-- - --i * ( i = -3 ) * i++ + ++i;printf("i = %d\n", i);return 0;
}

这个是同样的道理,虽然知道优先级,但是结合性中的操作数什么时候准备不确定,你看看在不同的编译器操作的结果:

同样是个垃圾代码

1.3.6 第六题讲解

#include <stdio.h>
int fun()
{static int count = 1;return ++count;
}int main()
{int answer;answer = fun() - fun() * fun();printf( "%d\n", answer);//输出多少?return 0;
}

()函数调用符号优先级最高,但是这里有三个,到底先调用哪个呢??这又不确定了.

  • vs编译器是从左往右依次调用的,结果为-10.
  • 但是其他编译器呢??大家去试试gcc,codeblocks,Devc++,你一定会发现完全不一样.

1.3.7 第七题讲解

再说这个题之前,博主一定要批判某些高校,为什么呢??学校教大家++符号时候是不是最喜欢用这种类型来考大家?在这明确告诉大家,这完全是在浪费时间!!!因为这种代码根本没有意义!!!.就是垃圾代码

#include <stdio.h>
int main()
{int i = 1;int ret = (++i) + (++i) + (++i);printf("%d\n", ret);printf("%d\n", i);return 0;
}

首先,()括号的优先级最高,但是有三个,到底先计算哪个?
其次,一个i的变化,会不会影响另外的?这里也不确定.和第四题我们说的那个编译之前c到底什么时候准备一样.不确定.!!!

  • vs编译器的值是 12 4
  • gcc编译器的值是 10 4
    不同的编译器不同的值,结果不一样,这样的代码不配叫代码.!!!

所以,以后看到这种题直接跳过,没有意义.

总结:

  • 知道了什么是整型提升与截断
  • 知道了什么是算术转换
  • 知道了什么操作符的属性,以后不能写出这种类似的垃圾代码.

C语言中的这个小细节你知道吗?相关推荐

  1. 【山东日照seo招聘】网站SEO优化中注意哪些小细节?

    [山东日照seo招聘]网站SEO优化中注意哪些小细节? 1.网页标题要合理     网页标题的重用占SEO优化过程中的40%,如果网页标题没有做好,那么在后期的优化过程中,就会事倍功半,网页标题主要从 ...

  2. 长假多图-生活中产品的小细节

    再长的休假也有结束的时候,今天第一天上班.假期中跑了一些地方,拍了一些照片,晚上整理起来,发现还是挺职业病的,特地拍摄了一些生活中产品的小细节,分享给大家. 先是在南京,国庆节前几天,都是街头随意拍摄 ...

  3. 王者荣耀游戏中的这些小细节,你知道吗?

    本人玩王者荣耀的第四个赛季,目前才王者27星,不过最近看到了一些小细节,大家看下是不是都知道了? 1,讲一个奇怪的知识,好像是一诺说的,射手出门先买鞋,到高地卖了,节约一秒到线时间. 2,达摩踢云中君 ...

  4. 关于在阅读nnUNet代码中的一些小细节的记录(一)

    首先,感谢paper桑大佬关于nnUNet项目的解释,我从中获益很多.本片是关于nnUNet代码中我看到的认为可能比较重要的某些细节的记录. 1.推理阶段.在nnUNet/nnunet/preproc ...

  5. 微信小程序的冥冥中拥有的小细节

    1.微信小程序的多目运算符 {{问题一?问题一成功:(问题一失败且判断)?问题二成功:问题二失败}} 2.关于微信小程序分包 小程序分包,一个包不能超过2m,不能超过8个分包,主包不能超过2m 3.微 ...

  6. 【c++师傅领进门,修行靠个人】第五篇:C++类和对象中的一些小细节

    面向对象的总结 1 初始化列表 2 如何突破封装 3 了解静态成员 4 类也能套娃 5 面向对象总结 1 初始化列表 初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成 ...

  7. 关于在阅读nnUNet代码中的一些小细节的记录(二)

    1.推理阶段:在nnUNet/nnunet/network_architecture/neural_network.py的250行的_get_gaussian函数. def _get_gaussian ...

  8. 电脑c语言小游戏,C语言中的一个小游戏的排行榜系统...

    我把你的代码改了一下,我已经运行过了,你看看 #include #include #include int play(int suiji); void paihangbang(struct p a[1 ...

  9. r语言remarkdown展示图_R语言中的十个小技巧

    一.switch函数 我喜欢swith().它基本上是根据另一个变量的值来选择其值的if语句的一个方便的缩写.我发现当我编写代码时,根据您先前的选择需要加载不同的数据集时,它特别有用.例如,如果您有一 ...

最新文章

  1. 又一款4800像素手机曝光:vivo V15 Pro
  2. (59)逆向分析 KiSwapContext 和 SwapContext —— 线程切换核心代码
  3. 表面粗糙度的基本评定参数是_表面粗糙度全方位解析,及表面粗糙度对照表
  4. mobi格式电子书_进阶能力 | 了解常见的电子书格式
  5. python3.8.4rc1_Python3.8.4rc1 官方正式版
  6. Maven聚合工程怎么变回普通的Maven工程
  7. 有向无环图描述表达式
  8. Day 41 Rsync备份
  9. 那些不得不提的坑(持续添加中)
  10. python如何制作一个任意列表_我要悄悄学Python之列表(一)
  11. 龙芯指令集也可以开源
  12. SELECT COUNT用法
  13. 275页PDF:《编写高质量代码:改善Python程序的91个建议》
  14. 悬臂梁振动方程及仿真
  15. word文本框中插入文本框_如何在Word中打印隐藏的文本
  16. 【干货分享】 淘宝客发朋友圈的技巧
  17. 【微信小程序】WXML WXSS JS
  18. 做月嫂这个行业好不好,月嫂一年能挣多少钱
  19. Kubernetes 企业集群建设规划
  20. 第1章 计算机网络和因特网-计算机网络

热门文章

  1. python实现朗读内容
  2. ct值在哪里看_如何看懂电流互感器铭牌
  3. 一团燃烧人性的实验之火——《野火(1959)》影评
  4. cs223w课程笔记7-GNN2
  5. 毕玄:我在阿里的十年技术感悟 1
  6. 记录一下今天安装tomcat时遇到的问题(初学者笔记)
  7. 华为强制升级鸿蒙,华为手机升级鸿蒙的方法,有哪位升级成功的吗?
  8. 百度量子计算机研究所在哪,百度成立量子计算研究所
  9. 著名杀毒网站 江民再次被黑
  10. BitTorrent (协议)