2011-02-11 83 views
0

这里是一个wchar_t的*字符串转换为一个char *字符串的C代码:致命错误*为char *转换

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

注意:`*`结尾是:`wchar_t *`和`char *`。 – 2011-02-11 10:35:50

+0

感谢您的精确。 – Dunaril 2011-02-11 10:37:58

+0

@Marcelo:这是一个品味和习惯的问题,并且有充足的理由像Dunaril那样编写它(例如`int * a,b;`表示`b`也是``int`的指针)。 – Thomas 2011-02-11 10:38:45

回答

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)必须分配空间那个字节。有时候有点吸吮。

因此,每当您看到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字节,包括字节数

4

对于'\0'终结符字符,您需要一个额外的字节。 wcslen不包括在它返回的长度!

要正确地做到这一点,你不只是需要通过length+1wcstombs_smalloc

charString = (char *)malloc(length+1); 
wcstombs_s(&i, charString, length+1, myXML, length); 

即使这样,我怀疑这将无法正常工作。并非所有宽字符都可以映射到单个char,因此对于非ASCII字符,您需要多字节字符串中的额外空间。