【发布时间】:2009-02-16 03:55:53
【问题描述】:
我正在使用 GCC 在 64 位 Solaris 系统上调试一些开源代码,它将 2 字节字符 (wchar_t) 转换为 4 字节字符 (wchar_t)。因为 Solaris 和其他一些 Unix 一样将 wchar_t 定义为 4 字节,而不是 Windows 中的 2 字节。
现在我解决了这个问题,通过将指针算法放在两行上,但我不确定原始代码有什么问题。有什么线索吗?
原始代码
int StringCopy2to4bytes(const unsigned short* src, int src_size,
unsigned int* dst, int dst_size)
{
int cp_size = 0;
const unsigned short *src_end = NULL;
const unsigned int *dst_end = NULL;
unsigned int c1, c2;
src_end = src + src_size;
dst_end = dst + dst_size;
while (src < src_end)
{
c1 = *src++;
if ((c1 >= UNI_SUR_HIGH_START) && (c1 <= UNI_SUR_HIGH_END))
{
if (src < src_end)
{
c2 = *src;
if ((c2 >= UNI_SUR_LOW_START) && (c2 <= UNI_SUR_LOW_END))
{
c1 = ((c1 - UNI_SUR_HIGH_START) << UNI_SHIFT) +
(c1 - UNI_SUR_LOW_START ) + UNI_BASE;
++src;
}
}
else
return -1;
}
if (dst >= dst_end) return -2;
*dst++ = c1;
cp_size++;
}
return cp_size;
}
固定代码
int StringCopy2to4bytes(const unsigned short* src, int src_size,
unsigned int* dst, int dst_size)
{
int cp_size = 0;
const unsigned short *src_end = NULL;
const unsigned int *dst_end = NULL;
unsigned int c1, c2;
src_end = src + src_size;
dst_end = dst + dst_size;
while (src < src_end)
{
c1 = *src; //FIX
++src;
if ((c1 >= UNI_SUR_HIGH_START) && (c1 <= UNI_SUR_HIGH_END))
{
if (src < src_end)
{
c2 = *src;
if ((c2 >= UNI_SUR_LOW_START) && (c2 <= UNI_SUR_LOW_END))
{
c1 = ((c1 - UNI_SUR_HIGH_START) << UNI_SHIFT) +
(c1 - UNI_SUR_LOW_START ) + UNI_BASE;
++src;
}
}
else
return -1;
}
if (dst >= dst_end) return -2;
*dst = c1; //FIX
++dst;
cp_size++;
}
return cp_size;
}
编辑:记录一下,代码不是我的,我只是在用,正好在调试,不是说有什么大的区别,但是出处是相当的大,所以我试图用镊子修复它,而不是重构所有东西,反正错误就是错误,我需要修复它并向作者发送错误消息。
常量是:
/* unicode constants */
#define UNI_SHIFT ((int) 10 )
#define UNI_BASE ((unsigned int) 0x0010000UL)
#define UNI_MASK ((unsigned int) 0x3FFUL)
#define UNI_REPLACEMENT_CHAR ((unsigned int) 0x0000FFFD)
#define UNI_MAX_BMP ((unsigned int) 0x0000FFFF)
#define UNI_MAX_UTF16 ((unsigned int) 0x0010FFFF)
#define UNI_MAX_UTF32 ((unsigned int) 0x7FFFFFFF)
#define UNI_MAX_LEGAL_UTF32 ((unsigned int) 0x0010FFFF)
#define UNI_SUR_HIGH_START ((unsigned int) 0xD800)
#define UNI_SUR_HIGH_END ((unsigned int) 0xDBFF)
#define UNI_SUR_LOW_START ((unsigned int) 0xDC00)
#define UNI_SUR_LOW_END ((unsigned int) 0xDFFF)
【问题讨论】:
-
这个问题有点令人困惑——你不能同时让 wchar_t 为 2 个字节和 4 个字节。另外,您使用的是哪个版本的 GCC?
-
操作系统使用 wchar_t(4) 但需要通过网络将字符数据作为 wchar_t(2) 传输到其他系统,因此在两者之间进行转换
-
使用 4.2.4 为两个列表生成的代码完全相同。
-
常量的值是多少?我认为它们可能是:枚举 { UNI_SUR_HIGH_START = 0xD800, UNI_SUR_HIGH_END = 0xDBFF UNI_SUR_LOW_START = 0xDC00, UNI_SUR_LOW_END = 0xDFFF, UNI_SHIFT = 11, UNI_BASE = 0x10000 };我对 UNI_BASE 最没有信心。
-
嗯,它们是#defines,这并不酷,但你的值是正确的