小明打饭的问题?
的有关信息介绍如下:
又黑我程序员…………
其实是溢出了,和计算机表示数字的方法有关,简单解释一下。
这样的8个位是一个字节,可以用二进制的方式来表示一个数字,比如上图的00001011就是十进制的11,计算方法是
「S表示这个数,x表示从右往左数第i位上的数字。」
所以可以看出来,这8个位可以表示从00000000到11111111,也就是0到255,一共256个数字。
这种表示法我们暂时称为「unsigned int」,不用看懂因为单词啦,只是个名字,叫小红表示法也行。
但是这样的话有一个不好的地方,负数就无法表示了,所以有人就想了另一种表示办法,让这256个数字不表示0-255,而是表示-128到127。
怎么做呢?
我们把第一位单独拿出来作为符号位,是0的时候表示这是一个正数,是1的时候表示这是一个负数。并且我们规定:如果符号位是1的话,则这个数的绝对值就是「不管符号位,其它位的1变成0,0变成1之后再加1所代表的数值」。
有点绕,举个例子。
这个数。首先看符号位是1,确定这是个负数,把符号位去掉变成这样。
然后把0和1互换
然后加1
现在套用开始的求S的公式,这是 1+2+4 = 7
这个数是十进制的7,所以开始的11111001表示-7。
这种表示数字的方法叫做「int」
所以当我们用这种表示法想表示负数的时候,就逆着执行上面这几步。
再次举例,比如想表示 -20。
先确定了符号位是「1」。
然后用7位二进制表示出20-1=19,是0010011。
然后01互换,得1101100,再加上符号位1,得到-20的int型表示形式:
11101100
这两种表示方法各自有各自的使用情形~~
好了基础知识讲完了,现在开始讲故事,要用二进制的眼光看~。
-----------------------------------------------------------------
小明卡里只有8毛钱 =
小明卡里有00001000毛钱。
本来想打个6毛的饭结果不小心按了9毛的 = 小明卡里有 -1 毛钱
一起算一下-1用「int」表示法是怎么表示的~~1-1=0,表示为0000000,然后01互换,得到1111111,然后加上符号位,得到11111111。
「其实并不是用-1的int型表示法算出的11111111,因为写的太多怕大家懒得看,所以暂且就看成用-1的int型算出来的吧。具体描述请戳:
」
所以现在是,小明卡里有11111111毛钱。
发现木有!?11111111如果用「unsigned int」的表示法来看,是255!
所以段子里说「忽然疯狂地喷出255两饭」!
其实这是有问题的……如果逻辑正常应该发生的是,吐出9毛钱的饭,然后小明之后刷卡会显示他有255毛钱,恩。
-----------------------------------------------------------------
下面小明大吼烫烫烫烫烫烫烫烫烫烫烫烫的梗…………
妈蛋今天太晚要睡觉了明早起来更。
先这样。
-----------------------------------------------------------------
我来更新了~~
烫烫烫的这个问题和上面的关系不大,需要另外两个基础知识,我慢慢说~~
首先是16进制表示法,就是把2进制表示的数,每4位分成一段,计算出这4位的数值,用一个数来表示。因为4位二进制能表示0-15这16几个数,而十进制只用一位的话没办法10及以上的数,所以我们用ABCDEF表示10、11、12……15,就形成了16进制。
例子
恩,就是这样,所以这个数在16进制下被表示为9E,应该挺好懂吧~~
下一个基础知识是关于计算机怎么储存文本的。
计算机很可怜的……内存里全都是和上面那样一个一个的小格子,只能放0或者1,不能直接放字母或者符号或者汉字进去的……所以计算机是怎么表示文本的呢?
大家都想的到,一个数字代表一个文字呗~~所以外国人就弄出了我们广为人知的ASCII表。「想看看的点这里:
」,对了提醒一句~千万别去背这个表啊啊啊啊~~
比如我们可以看到 “0” 的ASCII码是48,所以当内存里的一段存着30「十六进制」的时候,我们要求计算机把这一段东西当作文本输出,就会输出一个“0”。
如果要表示一段话的话,结尾要给一个标志。因为内存是连续储存的,一般我们下命令是这样:「把从0xBF9A9E1B开始的字符串输出出来」。
那一串古怪的十六进制不要在意~就像门牌号一样,只是标志了一个内存中的地址,比如现在就表示那一段话里 「I」 所在的地址。
然后计算机就开始从「I」按照ASCII表开始一个一个的输出文本,当他发现下一个方格里是0的时候,则认为到达了字符串尾,不继续输出了。
但是经常会有萌萌的程序员忘记在末尾加0,而我们又不知道字符串的后面有一些什么内容~~~但是计算机还是会傻傻的一直往后面输出的~~
嘛,可以看到,ASCII码只用了0-127这128个数字,而8位二进制能表示255个数字~~所以那些剩下的就用来表示各种各样的文字了~~但是因为中文字有好多好多好多~100多个数字表示不下,所以需要用16位甚至更多位的数字来表示~
具体的表示方法分了好多好多种,比如ANSI,UTF-8,CP936,GB2312,Windows家族等等……感兴趣的可以看看维基:
嘛,然后我们现在计算机可以输出汉字了~~再加上萌萌的程序员忘记在末尾加0,所以计算机就越过了我们要他输出的边界,继续输出了内存里一些不是储存文字的东西……具体表现就是乱码QAQ
不过很好玩的是,程序员申请的内存的后面,经常被填充为「CCCCCCCCCCCCCC……」这样的数字……而CCCC在特定的编码「MBCS」下看的话表示的就是烫这个汉字…………
所以有可能会出现这样的情况:
hello world!烫烫烫烫烫烫烫烫烫烫烫烫烫
可以参考这个问题:
---------------------------------------------------------
恩,差不多讲完了~~其实这个段子就两个点,溢出和字符串末尾没加0,而且机器不可能吐出255两饭的T^T,逻辑错了,当然这是为了后面小明喊出「烫烫烫」而设计的~感觉还设计的挺好~~
---------------------------------------------------------
PS.
兄在评论提醒说 unsigned int 的问题,确实 unsigned int 和 int 不太可能只有 8 位,以上只是为了叙述方便取了 unsigned int 和 int 这两个大家习惯的类型名称。其实它们的长度和编译器有关,比如我这就是4字节32位~但是数字表示的方法大家都是相通的,我为了叙述和表示方便表格只画了8个格子~请大家注意活学活用么么哒。
另外如果上面哪里有写错或者错别字typo的也请大家指正~QAQ

