scanfは領域を破壊するか？

文字列を数値(short,byteも)に変換する際に、scanfを利用していたのだけど、「領域破壊するんじゃない？」と言われて調べた。

[scanf 関数の型フィールド文字|(MSDN)](https://msdn.microsoft.com/ja-jp/library/6ttkkkhh.aspx)
> d 10 進整数。int へのポインター。 

※ソースはswscanf_sを利用しているが、結果は同じだと思う。

```cpp:test.cpp
	//  swscanf_sは領域を破壊するか？
	int rc = 0;

	byte			bary[10];
	unsigned short	usary[10];
	short			sary[10];
	unsigned int	uiary[10];
	int				iary[10];

	byte			bvalue = 0;

	std::wstring	wstrTempD = L"255";

	// 破壊していないことを確認するため、既定値として0x11をすべてに設定する。
	memset(bary,	0x11,	sizeof(bary));	// ->0x11,0x11....
	memset(usary,	0x11,	sizeof(usary));	// ->0x1111,0x1111....
	memset(sary,	0x11,	sizeof(sary));	// ->0x1111,0x1111....
	memset(uiary,	0x11,	sizeof(uiary));	// ->0x11111111,0x11111111....
	memset(iary,	0x11,	sizeof(iary));	// ->0x11111111,0x11111111....

	rc = swscanf_s(wstrTempD.c_str(),L"%d",bary);	// ->0xff,0x00,0x00,0x00,0x11,....
	rc = swscanf_s(wstrTempD.c_str(),L"%d",usary);	// ->0x00ff,0x0000,0x1111,....
	rc = swscanf_s(wstrTempD.c_str(),L"%d",sary);	// ->0x00ff,0x0000,0x1111,....
	rc = swscanf_s(wstrTempD.c_str(),L"%d",uiary);	// ->0x000000ff,0x11111111....
	rc = swscanf_s(wstrTempD.c_str(),L"%d",iary);	// ->0x000000ff,0x11111111....

	bvalue = bary[0];	// アクセスすると、255ではあるが、領域を思い切り破壊…。

```

やっぱ壊してました。

```cpp:test.cpp
	// 変換としてはintに格納し、byteやshortにキャストして使うのがメモリ的には安全そう。
	bvalue = (byte)uiary[0];
	// 精度が落ちる可能性があるので、変換後にサイズチェックした方がいいかもね！
```

おまけ。%cの時の挙動

```cpp:test.cpp
	memset(bary,	0x11,	sizeof(bary));
	memset(usary,	0x11,	sizeof(usary));
	memset(sary,	0x11,	sizeof(sary));
	memset(uiary,	0x11,	sizeof(uiary));
	memset(iary,	0x11,	sizeof(iary));

	lRc = swscanf_s(wstrTempD.c_str(),L"%c",bary);	// ->0x32,0x00,0x11,0x11,0x11,....
	lRc = swscanf_s(wstrTempD.c_str(),L"%c",usary);	// ->0x0032,0x1111,0x1111,....
	lRc = swscanf_s(wstrTempD.c_str(),L"%c",sary);	// ->0x0032,0x1111,0x1111,....
	lRc = swscanf_s(wstrTempD.c_str(),L"%c",uiary);	// ->0x11110032,0x11111111....
	lRc = swscanf_s(wstrTempD.c_str(),L"%c",iary);	// ->0x11110032,0x11111111....

```
文字だから？か、後ろにNULLが挿入されるのかな。それか、wcharだからかもしれませんね。

###追記
short型は"%hd"で、char(byte)は"%hhd"で読み取れるとのご指摘を確認！
調べてみたところ、プレフィックスで読み取れる範囲を指定できるようです。

[scanf 関数の文字幅指定|MSDN](https://msdn.microsoft.com/ja-jp/library/xdb9w69d.aspx)

```cpp:test.cpp
			byte			bary[10];
			unsigned short	usary[10];
			short			sary[10];
			unsigned int	uiary[10];
			int				iary[10];

			byte			bvalue = 0;

			std::wstring	wstrTempD = L"255";

			// 破壊していないことを確認するため、既定値として0x11をすべてに設定する。
			memset(bary,	0x11,	sizeof(bary));	// ->0x11,0x11....
			memset(usary,	0x11,	sizeof(usary));	// ->0x1111,0x1111....
			memset(sary,	0x11,	sizeof(sary));	// ->0x1111,0x1111....
			memset(uiary,	0x11,	sizeof(uiary));	// ->0x11111111,0x11111111....
			memset(iary,	0x11,	sizeof(iary));	// ->0x11111111,0x11111111....

			rc = swscanf_s(wstrTempD.c_str(),L"%hd",bary);	// ->0xff,0x00,0x11,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hd",usary);	// ->0x00ff,0x1111,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hd",sary);	// ->0x00ff,0x1111,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hd",uiary);	// ->0x111100ff,0x11111111....
			rc = swscanf_s(wstrTempD.c_str(),L"%hd",iary);	// ->0x111100ff,0x11111111....

			// 破壊していないことを確認するため、既定値として0x11をすべてに設定する。
			memset(bary,	0x11,	sizeof(bary));	// ->0x11,0x11....
			memset(usary,	0x11,	sizeof(usary));	// ->0x1111,0x1111....
			memset(sary,	0x11,	sizeof(sary));	// ->0x1111,0x1111....
			memset(uiary,	0x11,	sizeof(uiary));	// ->0x11111111,0x11111111....
			memset(iary,	0x11,	sizeof(iary));	// ->0x11111111,0x11111111....

			rc = swscanf_s(wstrTempD.c_str(),L"%hhd",bary);	// ->0xff,0x00,0x00,0x00,0x11,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hhd",usary);// ->0x00ff,0x0000,0x1111,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hhd",sary);	// ->0x00ff,0x0000,0x1111,....
			rc = swscanf_s(wstrTempD.c_str(),L"%hhd",uiary);// ->0x000000ff,0x11111111....
			rc = swscanf_s(wstrTempD.c_str(),L"%hhd",iary);	// ->0x000000ff,0x11111111....

```
"%hd"は領域を破壊せずに読み取れました！"%hhd"は%dと同じ挙動に…。

### 追記
Visual C++では%hdまでで%hhdがないとのことでした。無念。
[scanf 関数の文字幅指定|MSDN](https://msdn.microsoft.com/ja-jp/library/xdb9w69d%28v=vs.120%29.aspx)