前言
C语言是如今最重要、最流行的编程语言之一,相对于其他程序设计语言,C语言更偏向底层结构化设计,提供对硬件更精准的控制,但也要求使用者更关注指针、位等字节级编程,本文以C语言为载体,研究字节级信息的存储和相关特性,讨论字符串、整数、浮点数的编码方式和相关隐患。不正之处,敬请指教
一、位+上下文
众所周知,现代计算机存储和处理的信息以二进制信号表示,即0和1。计算机内都是以0、1bit串存储信息,区分不同信息的唯一方法是根据解析0、1bit串的上下文。
首先,我们来思考这么个问题:给定一个串0110 0001
,代表什么含义呢?
在没有任何上下文的时候,我们直观的猜测这是个数字,将二进制转换为十六进制为0x61
,转换为十进制则为97
。
若进一步假定计算机在读取串0110 0001
的上下文是解析ASCII码,则串0110 0001
被计算机解释为ASCII码中的字符a
。但若设定计算机在读取串0110 0001
的上下文是unsigned char
掩码,则0110 0001
不代表任何含义,假如计算机在读取该串的上下文是引用一个字长为8bit
的指针,则0110 0001
就代表着地址97
。
单独的bit串并没有意义,信息是通过位+上下文承载的,相同的位串在不同上下文被解释成不同的信息。
二、表示字符串
C语言中的字符串被编码为以null
结尾的字符数组,字符串的每个字符通常以ASCII字符码进行编码。
//"123"存储为:0x31 0x32 0x33 0x00
//二进制表示:0011 0001 0011 0010 0011 0011 0000 0000
char *str1 = "123";
//"abc"存储为:0x61 0x62 0x63 0x00
//二进制表示:0110 0001 0110 0010 0110 0011 0000 0000
char *str2 = "abc";
复制代码
字符串的存储方式是不受字节顺序和字长影响的,因此字符串的可移植性是最好的。
三、表示整数
C语言数字编码体系是真实世界数字体系的近似表示,在某系特性上存在一定的差异。
打个比方,C语言用char
类型变量存储[-128,127]
共256个整数,在使用如下表达式时:
/*例1*/
char x = -128;
char y = -x;//真实世界y应该是128,但是在C语言中,y还是-128!
/*例2*/
char x = 100,y=30;
char sum = x+y;//真实世界y应该是130,但是在C语言中,y
是-126!
复制代码
若对C语言数字编码体系不了解,很容易导致程序出现极其隐秘的bug。下面我们着重讨论C语言是如何表示整数、浮点数。
(一)表示无符号
1. 概述
C语言针对整数提供两种编码方式:无符号编码(unsigned)、有符号编码(signed)。
首先,我们来看一下十进制的正整数表示方式,思考我们如何解释123
数字。应该为。
类比到无符号8bit
的二进制0110 0001
,有: