这是一个将wchar_t *字符串转换为char *字符串的C代码:
wchar_t *myXML = L"<test/>";
size_t length;
char *charString;
size_t i;
length = wcslen(myXML);
charString = (char *)malloc(length);
wcstombs_s(&i, charString, length, myXML, length);
代码编译但在exectution处它检测到最后一行的致命错误并停止运行。
现在,如果我用这一行替换最后一行:
wcstombs_s(&i, charString, length+1, myXML, length);
我刚刚为第三个参数添加了+1。然后它完美地工作......
为什么需要添加这个技巧?或者我的代码中的其他地方是否有缺陷?
答案 0 :(得分:4)
'\0'
终止符需要一个额外的字节。 wcslen
在返回的长度中不包含此内容!
要做到这一点,您不仅需要将length+1
传递给wcstombs_s
,还需要传递给malloc
:
charString = (char *)malloc(length+1);
wcstombs_s(&i, charString, length+1, myXML, length);
即便如此,我怀疑它无法正常工作。并非所有宽字符都可以映射到单个char
,因此对于非ASCII字符,您将需要多字节字符串中的额外空间。
答案 1 :(得分:2)
DESCRIPTION
The wcslen() function is the wide-character
equivalent of the strlen(3) function. It determines
the length of the wide-character string pointed to by
s, not including the terminating L'\0' character.
诀窍是你应该总是寻找表格的代码:
string = malloc(len);
非常可疑,因为wcslen(3)
和 strlen(3)
都返回字符串长度而没有nul字节,并且malloc(3)
必须使用该字节分配空间。 C有时候很糟糕。
因此,每当您看到string = malloc(len);
而不是string = malloc(len+1);
时,请务必仔细阅读len
的分配方式。
<击> 撞击>
<击>char String = (char *)malloc(length + 1);
击> <击> 撞击>
应该做的伎俩。 :)
修改强>:
最好首先询问wcstombs()
要分配的大小:
size_t len = wcstombs(NULL,src,0) + 1;
char *dest = malloc(len);
len = wcstombs(dest, src, len);
if (len == -1) /* handle error */ ...
+1
为ascii nul分配,wcstombs()
将报告进行转换所需的内存量。它将进行转换两次,一次跟踪所需的内存,然后一次存储结果,但维护起来会更简单。第二次,当它存储结果时,它将写入最多len
个字节,包括ascii nul 。