今天看到阮一峰的一篇文章,想起了大学一件有趣的事。
当时在做一个智能家居项目,我负责硬件部分(主要是基于 cc2540 芯片),设计原理图、PCB 以及芯片驱动、蓝牙协议栈开发,另外两个师兄分别做安卓和苹果的客户端。
给出控制指令表,客户端进行对接,比如 0xABCD
代表开,0xEEEE
代表关,做安卓的师兄很快就对接完成了,iOS 的师兄发现有一些指令可以接收到,一些丢失了,一直找不到原因,因为安卓那边正常,所以没有怀疑硬件问题。
搞了好久之后发现,就是大小端的问题。
“endian”一词来源于十八世纪爱尔兰作家乔纳森·斯威夫特(Jonathan Swift)的小说《格列佛游记》(Gulliver's Travels)。小说中,小人国为水煮蛋该从大的一端(Big-End)剥开还是小的一端(Little-End)剥开而争论,争论的双方分别被称为“大端派(Big-Endians)”和“小端派(Little-Endians)”。
1980年,丹尼·科恩(Danny Cohen),一位网络协议的早期开发者,在其著名的论文"On Holy Wars and a Plea for Peace"中,为平息一场关于字节该以什么样的顺序传送的争论,而第一次引用了该词。
就像下图,同样是 32 位整数,有的硬件是顺序记录在内存中,有的是反过来,数据传输的时候也是如此。
上面的 bug 就很清楚了,硬件和软件的大小端不匹配,对于 0xEEEE
的指令,大小端都一样,对于 0xABCD
大小端匹配就错了。
那为什么安卓的那位师兄没出错呢?因为他用的正则表达式 而不是 ==
号匹配。
更多资料可看:字节顺序。