Contents
  1. 1. char *
  2. 2. NSData 表示的字符串
  3. 3. 二进制的字符串
    1. 3.0.1. 例子

二进制是没有意义的,是编码协议赋予了其意义。

这句话是我编的。

char *

如果是 char * 应该比较清晰了

二进制表示:|000000001|00000002|00000000|
十六进制表示:|01|02|00| 每八位转换成一个字节

比如

NSString *string = @"0123\n";
char *c = [string UTF8String];

在这次运行中 c 地址是 0x0000000103c06dae,内存内容是

30 31 32 33 0a 00 68 61 73 68 00 54 51 2c 52 00
0…1…2…3…nl…0…x…x…x…x…x…x…x…x…x…x

30 是 ascii 表中的 ”0“
0a 是 ascii 表中的 nl,换行

string 的 length 是 5,\n 单独作为一个字符。

如果 string = @”0123好” 混入了 ascii 无法处理的字符会怎么样呢?

30 31 32 33 e5 a5 bd 00 00 00 00 00 00 00 00 00

多出了 e5 a5 bd,这个就是”好“的二进制表示了,准确的讲是 utf8 编码下的二进制表示。utf16 下就不是这个编码了。

NSData 表示的字符串

c 字符串比较熟悉了,那么 iOS 平台上的 NSData 呢?

其实 NSData 就是对无类型数组的一个封装。

嗯,这句话也是我编的

NSString *string = @"0123好";
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

一个 NSData 对象至少有这样的成员变量

unsigned long long _length;
unsigned long long _capacity;
void * _bytes;

在这个例子中 _length 是 7,_capacity 是 8。后者比前者多 1,是字符串 null 结尾的缘故。别的类型估计这俩就是一样的。_bytes 就承载了真正的数据。这种模式跟图片的文件格式或者 OpenCV 里的图片对象设计都差不多,用一个大数组存放 raw 数据,剩下的内存放属性。所以看下这个数据里放的啥,不用想了,就是上一节的 c 字符串

30 31 32 33 e5 a5 bd 00 27 00 00 00 00 00 00 00

二进制的字符串

一个字符串,包含非 ascii 码的二进制字符串计算机是怎么存储或者表示呢?

30 31 32 33 e5 a5 bd 00 27 00 00 00 00 00 00 00 是二进制的 ”0123好“

无数的面试题告诉了我非 ascii 的字符使用 unicode 表示,那么 unicode 跟 utf8 到底是什么关系呢?今天终于搞清楚了。

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

阮一峰先生这篇文章通俗易懂,感谢他我很快就弄明白了。

unicode 一个巨大的表,里面包罗万象,世界各民族字符大一统、大融合。

utf8 是把 unicode 优化了一波,直接使用 unicode 来编码会造成极大的空间浪费。汉字要用三个字节表示,ascii 只需要一个。用一个字节单位来挨个解读编码又会把汉字这样的字符弄乱,强行每三个字节解码又会让 ascii 码平白无故增加两个字节的全零空间。更何况,要是还有五个字节的字符呢?

utf8 是变长的,白话就是同样是 utf8,这个字符是一个字节,别的可能是三个、四个。通过内存前面的 0、1 位置约定来蕴含本字符的编码要求。

例子

下面把二进制转成中文字符:

e5 a5 bd 转换成十六进制就是

1110 0101 1010 0101 1011 1101

前面有三个 1,是汉字。根据规则把 1110 后面的 0101,后续第一个 10 后面的 10 0101,再后一个 10 后面的 11 1101 取出来组合

0101 10 0101 11 1101

整理下

01011001 01111101

转换成十六进制

597D

查表得 597D 即为”好“。

Contents
  1. 1. char *
  2. 2. NSData 表示的字符串
  3. 3. 二进制的字符串
    1. 3.0.1. 例子