C++ - 将 char 转换为 wchar_t。出现段错误

C++ - Converting a char to wchar_t. Getting a segfault

我正在尝试编写从 istream 中读取字符并将其转换为 wchar_t 的小程序。我遇到了段错误。这是我的代码

#include <iostream>
using namespace std;

wchar_t read(istream &stream) {
 char *c;
 stream.read(c, sizeof(*c));
 cout << *c << endl;
 wchar_t retChar = static_cast<wchar_t>(*c);
 return retChar;
}

int main() {
 cout << "Write something" << endl;    
 read(cin);
}

我这里的逻辑是:

  1. 创建一个字符数组,因为只读需要字符数组。
  2. 以等于字符大小的字节为单位读取。即读取一个字符并将其存储在数组 c.
  3. 创建一个 wchar_t 并将该字符 *c 转换为 wchar_t。
  4. return wchar_t

因为我遇到了段错误,所以这里显然有问题。我看不到它。任何帮助将不胜感激。

非常感谢

单步执行代码,让 OP 了解发生了什么以及为什么它不起作用。然后,我们将看看如何尽可能接近他们的意图来做他们想做的事情。然后提示如何在 C++ 世界中更好地做到这一点。

wchar_t read(istream &stream) {
 char *c;

声明一个指针 c 并且不指向任何东西。 c 是一个未初始化的变量。可以把它想象成被邀请到史蒂夫家参加聚会,但没有人告诉你他住在哪里。无论你走到哪里,很有可能都不是史蒂夫的家。

 stream.read(c, sizeof(*c));

sizeof(*c) 将 return 一个字符的大小。可能是 8 位和 1 字节,但是 c 仍然没有指向任何东西所以这是 Undefined Behaviour。不知道该程序将做什么,但很可能它会将一个字节读入内存中某个未知的 space 中。也许这会导致崩溃,因为你不能在那里写。也许它覆盖了允许覆盖的内容并搞砸了其他内容。

 cout << *c << endl;

尝试打印出 c。如果程序在上面的 read 中幸存下来,那么它也能幸存下来的可能性很大,但这也是未定义的行为。

 wchar_t retChar = static_cast<wchar_t>(*c);

这实际上会将一个字符的数据值填充到一个宽字符中。它不会根据语言环境或任何其他字符编码进行转换。 char 是已定义为解释为字符的数字代码。强制转换会愚蠢地将字符值,比如 'A' 和 ASCII 编码放入 retCharretChar 现在等于 65。65 可以表示任何内容,具体取决于 wchar_t 使用的编码。它可能仍然意味着 'A',但抱歉 Ayn Rand,这是 A 很可能不是 A 的一种情况。

 return retChar;
}

做 OP 试图做的事情(暂时忽略有更好的方法):

#include <iostream>
using namespace std;
wchar_t read(istream &stream) {
 char c[2];

分配一个字符数组。为什么?因为我知道的最简单的方法是对字符串进行转换。

 stream.read(c, sizeof(c[0]));

c 现在是一个退化为指针的数组。我们只想读取一个 char,所以 sizeof(c[0]) 得到数组中第一个元素的大小。

 c[1] = '[=17=]';
 cout << c << endl;

Null 终止并打印。

 wchar_t retChar[2];

同样,数组。

 mbstowcs(retChar, c, 1);

使用已设置的任何语言环境将一个字符从字符转换为宽字符。在此处阅读有关语言环境的更多信息:http://en.cppreference.com/w/cpp/locale/setlocale

关于 mbstowcs 的文档:http://en.cppreference.com/w/cpp/string/multibyte/mbstowcs

 return retChar[0];
}

通过快速测试仪将所有内容放在一起:

#include <iostream>
#include <cstdlib>

wchar_t read(std::istream &stream)
{
    char c[2];
    stream.read(c, sizeof(c[0]));
    c[1] = '[=21=]';
    std::cout << c << std::endl;
    wchar_t retChar[2];
    mbstowcs(retChar, c, 1);
    return retChar[0];
}

int main()
{
    std::wcout << read(std::cin) << std::endl;
}

这很简单,但在 C++ 世界中很难看,您应该尽可能坚持使用 strings。 In that case look into std::wstring_convert.