glib中utf16的字节序

来源:互联网 发布:纸猫 澳大利亚 知乎 编辑:程序博客网 时间:2024/06/15 08:53

在glib中有许多操作unicode的函数,如g_utf8_to_utf16等,我们知道,utf16有大端(BE)和小端(LE)的区别,那么在glib中的utf16到底是大端还是小端呢,我们可以通过分析g_utf8_to_utf16函数的原码得出答案。

在g_utf8_to_utf16函数中,通过如下代码先把把utf8转换成unicode

gunichar wc = g_utf8_get_char (in);

然后直接通过如下代码把unicode值转换成utf16编码:

 if (wc < 0x10000)
    {
      result[i++] = wc;
    }
      else
    {
      result[i++] = (wc - 0x10000) / 0x400 + 0xd800;
      result[i++] = (wc - 0x10000) % 0x400 + 0xdc00;
    }

我们可以看到,当unicode值为BOM时,直接把unicode的值赋值给了utf16编码,那么g_utf8_get_char返回的unicode值的字节序就是glib中utf16的字节序,我们接下来再分析一个上述unicode值的字节序。

在g_utf8_get_char中,glib通过宏UTF8_GET把utf8编码转换成unicode值,

gunichar
g_utf8_get_char (const gchar *p)
{
  int i, mask = 0, len;
  gunichar result;
  unsigned char c = (unsigned char) *p;

  UTF8_COMPUTE (c, mask, len);
  if (len == -1)
    return (gunichar)-1;
  UTF8_GET (result, p, i, mask, len);

  return result;
}

我们来看一下这个宏的定义:

#define UTF8_GET(Result, Chars, Count, Mask, Len)                  \
  (Result) = (Chars)[0] & (Mask);                          \
  for ((Count) = 1; (Count) < (Len); ++(Count))                      \
    {                                          \
      if (((Chars)[(Count)] & 0xc0) != 0x80)                      \
    {                                      \
      (Result) = -1;                              \
      break;                                  \
    }                                      \
      (Result) <<= 6;                                  \
      (Result) |= ((Chars)[(Count)] & 0x3f);                      \
    }

可以看到,unicode值就是通过把utf8编码字节逐个右移得到,我们可以思考一下,这样右移后,字节序由什么来决定?

举个例子:

我们有个数为:0x12345678,先保存到一个数组中,

unsigned char num[4];

num[0] = 0x12;

num[1] = 0x34;

num[2] = 0x56;

num[3] = 0x78;


如果我们执行这样的操作,那么i的值是多少呢?

unsigned int i =*(unsigned int*)num;


如果执行这样的操作,那么i的值是多少呢?

unsigned int i;

i  = (num[0] << 24) | (num[1] << 16) | (num[2] << 8 ) | (num[3]);


可以通过单步调试看一个i在内存中每个字节的值,再对比大端小端的概念思考一下。 

这里的答案是,在小端的window下,后一种操作的值为0x12345678,是一个正常的值,强调的是这里i的字节序是小端。

结论:

glib中utf16的字节序是由编译器决定的,而编译器一般是根据目标操作系统的字节序来设置,所以glib中utf16的字节序通常情况下是与操作系统当前工作的字节序相同的。



原创粉丝点击