対charとwchar_tいくつかの疑問の理解


charとwchar_についてt前者は1バイトを格納するために用いられ、後者は2バイトを格納するために用いられることを知っているので、アルファベット数字のようなascii符号化文字はcharで格納することができる.しかし、漢字は保存するのに2バイト必要なのでwchar_tは私たちのニーズに合致することができます.しかし、charが漢字の処理に使われているのをよく見ています.
1>char a[]=「こんにちは」;
printf("%s", a);
出力結果:こんにちは
解釈:charは1バイト、つまり半分の漢字しか保存できないのに、なぜ私たちが望んでいる結果を出力できるのでしょうか.我々はstrlen(a)で結果4を得ることができ、確かに1つのcharが1バイトしか残っていないようで、2つの漢字だから4つのcharが必要で、UltraEditによって「こんにちは」のバイナリ符号化は:c 4 e 3 ba c 3なので、a[0],a[1],a[2],a[3]で、それぞれこの4つの値に対応していることがわかります.つまり、a[0]またはa[1]を単独で取ると必ず欲しい漢字が得られないので、正しい結果を出力できるのは、コンパイラが左から右にできるだけ多くの合法的なデータを読み込むことで、a[0]とa[1]を組み合わせ、a[2]とa[3]を組み合わせて欲しい漢字を出力するからである.
2>memcpyを見ました_aの実装は、なぜwchar_にtタイプの漢字列をコピーしますか?まず、元の列とターゲット列はvoid*タイプであり、既知のタイプに変換する必要があります.char*に変換して1を足すと、次のバイト(wchar_tの場合は2バイトオフセット)を指しますが、漢字ごとに2バイトあるのでcountは漢字の個数の2倍、つまり半分の漢字でコピーされ、漢字1文字のコピーではありません.これらはメモリで動作するため、したがって、元の列とターゲット列のメモリの内容が同じであれば、どのようにコピーされているかは気にしません.ここから、この関数を使用するとエラーが発生しやすい場所がわかります.
memcpy_a(dst, src, wcslen(src));//エラー
memcpy_a(dst, src, wcslen(src) *sizeof(src[0]));//正しい
memcpy_a(dst, src, sizeof(src));//配列ならいいですが、もちろん配列がポインタに劣化してはいけません
最後に、ワイド文字関数で漢字を出力場合はヘッダファイルinclude,main関数の下の先頭::setlocale(LC_ALL,“Chs”);
#include <stdio.h>
#include <locale.h>
using namespace std;

void* memcpy_a(void *dst, const void *src, size_t count)
{
	void *ret = dst;

	while (count--)
	{
		*(char*)dst = *(char*)src;
		dst = (char*)dst + 1;
		src = (char*)src + 1;
	}

	return ret;
}

int _tmain(int argc, _TCHAR* argv[])
{
	::setlocale(LC_ALL, "Chs");

	wchar_t src[] = L"       ";
	wchar_t dst[128] = {0};

	memcpy(dst, src, wcslen(src) * sizeof(src[0]));
	wprintf(L"dst = %s
", dst); cin.get(); return 0; }