文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>C中八进制和十六进制转义字符揭秘

C中八进制和十六进制转义字符揭秘

时间:2010-05-14  来源:倒数第二位

C中八进制和十六进制转义字符揭秘

首先说明的是,这是小牛我在CU中第一篇博文,里面可能一些专业术语,名词都不是很规范,分析可能也有失偏颇,请各位大牛拍砖赐教!

 

在c中有一种数值型的转义字符,即’\ddd’的三位八进制转义字符和’\xdd’的两位十六进制转义字符。这两种转移字符其代表着一个字节大小的整数值字符。

首先什么是转义字符,顾名思义转义字符最终是一种字符,只不过它是被转义了一下。所以它是一个字符的本质是不会变的。这也就是上面为什么说“这两种转移字符其代表着一个字节大小的整数值字符。”,因为字符是一个字节大小的。它是一个字符,但是由一个整数(三位八进制或两位十六进制)表示,正如ASCII码表中整数值48代表字符’0’一样。只不过’\000’代表整数0,其对应ASCII码表对应的字符为NULL。解释的有点拗口,但是大致的意思就是这样。

 

其八进制转义字符测试代码8zhuanyi.cpp如下:

01  #include <iostream>

02  using namespace std;

03 

04  #define b '\001'

05 

06  int main()

07  {

08      cout<<"8 进制转移字符的sizeof大小:"<<sizeof(b)<<endl;

09      int a = b;

10      cout<<"putchar(a): ";

11      putchar(a);

12      cout<<endl<<"a Value is : "<<a<<endl;

13     

14      cout<<"putchar(b): ";

15      putchar(b);

16      cout<<endl<<"b Value is : "<<b<<endl;

17      printf("b的整数值为:%d\n", b);

18     

19      system("pause");

20      return 0;

21  }   

其输出打印结果如下:

结论分析:

可以看到,b是一个字符,所以cout<<b时输出的是一个笑脸,并且b的大小只有一个字节。根据b的内存大小就可以得知b肯定不是一个int整数,而是一个字符。并且b代表的整数值为1,对应为ASCII码表的值。

 

相同我们也可以看看’\xdd’的两位十六进制转义字符。

其十六进制转义字符测试代码16zhuanyi.cpp如下:

01  #include <iostream>

02  using namespace std;

03 

04  #define b '\x01'

05 

06  int main()

07  {

08      cout<<"16 进制转移字符的sizeof大小:"<<sizeof(b)<<endl;

09      int a = b;

10      cout<<"putchar(a): ";

11      putchar(a);

12      cout<<endl<<"a Value is : "<<a<<endl;

13     

14      cout<<"putchar(b): ";

15      putchar(b);

16      cout<<endl<<"b Value is : "<<b<<endl;

17      printf("b的整数值为:%d\n", b);

18     

19      system("pause");

20      return 0;

21  }

其输出打印结果如下:

 

通过上述两个演示代码,我再一次强调“这两种转移字符其代表着一个字节大小的整数值字符。”这一个原理。以下的分析测试可能与这个过程相互映衬。

 

问题1:超出范围

一个字节八位,八进制转义字符中,而三位的八进制有9位(每一位八进制相当于3位二进制),所以说'\ddd'表示的范围已经超出了一个字节的表示范围!然而这会发生什么了,不妨做一个实验。

将8zhuanyi.cpp中第4行的代码#define b '\001'换成#define b '\401'   

其输出如下:

通过对比输出可以看到,输出时没有任何变化的。为什么'\001'和'\401'的输出是一样的?我们将其转换为二进制来看一看。

'\001'    000 000 001

'\401'    100 000 001

而一个字符只有8位,转义字符'\001'和'\401'都有9位,于是我们情不自禁的就想到“截断”。如果真是截断,那么'\001'和'\401'所表示的字符的值就是一样的,舍弃了最高位的情况下,所以输出都是1,打印内容一样。

 

而十六进制转义字符两位十六进制刚好对应8位二进制,表示一个字符的范围,所以不会出现上述问题。

 

问题2:转义字符是否是有符号字符

关于这个问题只需将最高位,即8位置1,观察打印出来的数是否为正数就可以得到答案。修改将8zhuanyi.cpp中第4行的代码#define b '\001'换成#define b '\201'

其输出如下:

可见八进制转移字符是有符号的字符!(包括十六进制转义字符也一样)

 

问题3:由于八进制中只有“0——7”,如果转义字符中出现“非合法数字”8和9会怎么办?同样的问题是,’\xdd’十六进制中只有“0——9 和 A|a——F|f”,如果转义字符中出现了诸如‘G’之类的字符会是什么情况?

这个问题最好的办法就是做一个测试。修改将8zhuanyi.cpp中第4行的代码#define b '\001'换成#define b '\008'

其输出如下:

这个测试的结果就有点异常!首先转义字符的内存大小sizeof变为4而不是1,和int的大小一样。从某种意义上来说'\008'已不再是表示一个字符了,而是一个整数。

其次'\008'的整数值为56,很显然读的是字符’8’的ASCII码中的整数值56。而不是像“合法”情况下那样,直接读取的该整数值。所以这里面有一个更深层次也更隐晦的问题,就是'\008'中的8不再表示3位二进制,而是表示8位二进制。因为系统将8作为一个字符’8’来处理了。

为了验证这一点,再做一个测试。修改将8zhuanyi.cpp中第4行的代码#define b '\008'换成#define b '\018'

其输出如下:

对比前后两个输出,不经会发现一个问题。'\018'和'\018',putchar()都是8。但是其代表的整数值一个是312,而一个是56,这是为什么?

既然都是占4个字节,不妨转化为二进制来看一看。

'\018'   312  0000 0000  0000 0000  0000 0001  0011 1000

'\008'   56   0000 0000  0000 0000  0000 0000  0011 1000

这样我们就不难发现,putchar()函数是输出一个八位二进制的字符,是一个字节。而'\018'和'\008'都是四个字节,所以在调用putchar()函数时,系统会将其截断,取低8位。所以调用putchar()函数输出的结果都是一样。

这就说明一个问题,当转义字符中出现“非法”的字符8或9时,系统将会视为ASCII码的八位二进制来处理,因为它会当一个字符来处理,而不是一个数字来处理。而不再是“合法”情况下三位二进制处理。所以这个’8’可以是任意一个字符,诸如’A’等等。

 

但是上面的输出还有一个问题,解释不了。那就是'\018'中为什么1“合法”当数字处理,整数值为1;而8“非法”当字符处理,整数值为56。我们可以这样猜测,系统一开始并不知道转义字符中包含“非法”字符,所以系统“从左往右”读取转移字符时,先是按照正常的,合法的流程处理。先处理0,合法,值为0;接着处理1,也合法,值为1;最后处理8,不合法,所以值为56。拼在一起就是上面的结果

'\018'   312  0000 0000  0000 0000  0000 0001  0011 1000

 

按照这种逻辑下去,又有一个问题需要解释。假设有一种情况'\081',这个1是当“合法”数值处理,还是“不合法”当字符处理,测试一下。

修改将8zhuanyi.cpp中第4行的代码#define b '\018'换成#define b '\081'

其输出如下:

转换为二进制看一看:

'\081'  14385   0000 0000  0000 0000  0011 1000  0011 0001

                                    56(‘8’)     49(‘1’)

这样可以得知,1是当做“不合法”当字符处理。所以可以得出一个结论,当转移字符中出现了非法字符时,转义字符变为一个4个字节的整数,从左至右,从第一个非法字符开始一直往右的所有字符都被当成“非法”字符处理。包括诸如1,2之类。这样也主要是因为,其性质已经变了,变成了4个字节大小了。

问题三得出的所有结论,同样适应于十六进制转义字符。因为没有异议,所以就不再做演示代码了。我测试的过程中,两者的结果都是一样的。

 

问题4:输入的转义字符不是规定的长度,比如’\00’会是什么情况。

对于八进制转义字符而言,不足会补0,超过的话就变为4字节。

对于十六进制转义字符而言,不足会补0,超过的话也不会变为4字节,它会取最后两位。始终大小为1,除了碰到“非法”字符之外。
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载