如何在 C 中将 wchar_t 转换为 BYTE*
Posted
技术标签:
【中文标题】如何在 C 中将 wchar_t 转换为 BYTE*【英文标题】:How to cast a wchar_t to a BYTE* in C 【发布时间】:2013-06-14 09:09:42 【问题描述】:我想在通过流发送之前将wchar_t
变量转换为BYTE *
。
我有
wchar_t val[] = L"abc";
我尝试使用:
BYTE * bytes = (BYTE *)val;
读取字节时我没有所有字符;我只有第一个字符 - "a"
我想,我转换得不好wchar_t
。
我做错了什么?
编辑:
static void DASH_process_receive(rdpSvcPlugin* plugin, wStream* data_in)
int bytes;
wStream* data_out;
DASHPlugin* DASH = (DASHPlugin*) plugin;
fprintf(stderr, "DASH_process_receive:\n");
if (!DASH)
fprintf(stderr, "DASH_process_receive: DASH is nil\n");
return;
/* process data in (from server) here */
/* here we just send the same data back */
bytes = Stream_Capacity(data_in);
fprintf(stderr, "DASH_process_receive: got bytes %d\n", bytes);
wchar_t val[] = L"abc";
bytes = Stream_Capacity(data_in);
if (bytes > 0)
fprintf(stderr, "size wcslen val %zd\n", wcslen(val));
fprintf(stderr, "size of val %zd\n", sizeof(val)); //I Have 16
data_out = Stream_New((BYTE*)val, sizeof(val));
Stream_Copy(data_out, data_out,sizeof(val));
/* svc_plugin_send takes ownership of data_out, that is why
we do not free it */
bytes = Stream_GetPosition(data_out);
fprintf(stderr, "DASH_process_receive: sending bytes %d\n", bytes);
svc_plugin_send(plugin, data_out);
Stream_Free(data_in, TRUE);
编辑:读取数据
WTSVirtualChannelRead(VirtChannelParamsStart, 20000, (PCHAR)Message, sizeof(Message), &ulBytesRead))
unsigned short Message[1024];
CString paramsPourStarter;
paramsPourStarter = Message;
SetDlgItemText(IDC_ED_DASH_RESU,paramsPourStarter);
【问题讨论】:
【参考方案1】:bytes
的长度你怎么看?
如果sizeof(wchar_t) == 2
(假设你在一个小端主机上运行)byte
指向的数据看起来像
'a', '\0', 'b', '\0', 'c', '\0', '\0', '\0'
所以strlen
会在'a'
之后立即遇到空字符后停止计算它的长度
当您转换wchar_t
数组时,您还应该使用wcslen
计算其长度
BYTE * bytes = (BYTE *)val;
size_t len = wcslen(val) * sizeof(val[0]);
// pass len to any functions which are passed bytes
【讨论】:
simonic 谢谢你的回答,我已经用 wcslen(val); 得到了字节的长度;但我有相同的结果,当我记录 sizeof(wchar_t) 我有 16 而不是 2 当我记录 wcslen(wchar_t) 我有 3 而不是 8?为什么? @Pis 如果sizeof (wchar_t)
是 16,我会感到惊讶。sizeof val
可能是 16(sizeof (wchar_t) == 4
,val
包含 4 个元素)。 val
的前三个元素或非零,所以 wcslen(val) == 3
。但是非零的wchar_t
s 仍然包含0-bytes,因此普通的字符串处理函数认为它在第一个wchar_t
的第一个字节之后停止。
@Pis 我建议的len
计算中有错误。看看更新后的代码是否更适合您。
@simonc L
在val[] = L"abc";
中是什么意思 ?
@GrijeshChauhan 它指定 unicode (utf16) 字符的字符串文字。详情请见here。【参考方案2】:
转换很好,我假设您发送了正确的字节数。假设wchar_t
是一个 2 字节的 UTF-16 字符,可以使用 sizeof(val)
找到它,并且等于 8 用于您问题中的代码。或者,如果您的 wchar_t
是 4 字节 UTF-32 字符,则 sizeof(val)
将为 16。
问题将出在另一端,即读取数据的代码中。我可以想象三种明显的故障模式:
-
您未能读取整个缓冲区。也许您假设内容为空终止并读取到第一个零字节。这是不正确的,因为 null
wchar_t
实际上是两个零字节。
您正确读取了整个缓冲区,但您将数据解释为char*
而不是wchar_t*
。
您正确读取数据并将其正确解释为wchar_t*
。但是wchar_t
是发送方的 UTF-32 和接收方的 UTF-16。这意味着当数据实际上是 UTF-32 时,您会将数据解释为 UTF-16。
任何这些解释都可以解释为什么您只收到第一个字符。
无论如何,我认为您以错误的方式解决问题。您可能不应该通过网络传递 UTF-16/UTF-32。对文本使用面向字节的编码会更好,自然选择 UTF-8。
更新
您的更新使发生的事情更加清晰。您通过网络发送 UTF-32 数据,然后将该数据解释为 UTF-16(假设您的 Windows 程序是 Unicode 程序)。这种不匹配导致数据被错误解释,并解释了为什么您只收到第一个字符。就是上面的第 3 项。
为了解决这个问题,您需要非常清楚您的文本是如何编码的。您可以通过以下事实来观察您遇到的基本问题:您的问题中没有任何地方谈论文本编码。如果你想在不同的程序之间传递数据,你需要就通用的文本编码达成一致。同样,我建议您将 UTF-8 编码的文本放在网络上。
你还有一个问题,你假设文本是空终止的。如果你有一个传输错误,那么你的接收程序有一个缓冲区溢出。您需要解决的另一个问题是字节序。您需要所有各方就网络上的数据达成共同的字节顺序。使用网络字节顺序。
【讨论】:
我不知道。这取决于你的编译器。在 Windows 上是 8,在许多 *nix 平台上是 16。你仍然需要 UTF8。 我的编译器是 Mac OS 上的 XCODE 您的问题描述了在另一端读取数据失败。您没有显示您是如何读取数据的,因此我的回答不具体。除非你展示你是如何读取数据的,否则我不能说更多。 您显示的距离不够近。我们需要查看类型,以及如何显示字符串。 好的,很清楚现在发生了什么。我已经更新了我的答案。以上是关于如何在 C 中将 wchar_t 转换为 BYTE*的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ CLR 中将数组<System::Byte> 转换为 char*?
如何在 C 中将 short 转换为 unsigned char *buf?
如何在 C# 中将 List<byte> 转换为 byte[]?