忘却とは忘れ去ることなり・・・。
文字列あふれなんか上位層でカットして、下位層はそのままスルーして使ってしまえ!と実装していたのだが、Linuxみたいにリソースが裕福な環境だと、チェックを減らしてROMやスタックの消費を抑えるよりも、きっちりチェックして安全を求めることが優先されるらしい。
ちっ。
以前調べた気もするが、記憶が無いので調べ直そう。
過去記事は、こちら。
[c/c++]strncatはあふれても\0付加しない
https://hiro99ma.blogspot.com/2016/12/ccstrncat0.html
どちらかといえば、snprintf()は\0を付加するが、それ以外はやってくれない、と覚えるのが良いのか。
でも、strncpy()なんかはメジャーな気がするから、やってくれるかもしれない(よくわからない期待)。
01: #include <stdio.h> 02: #include <string.h> 03: 04: #define STRMAX (10) 05: 06: int main(void) 07: { 08: char str1[STRMAX + 1]; 09: 10: memset(str1, 'a', sizeof(str1)); 11: snprintf(str1, sizeof(str1), "12345678901234567890"); 12: printf("snprintf : [%s]\n", str1); 13: 14: memset(str1, 'a', sizeof(str1)); 15: strncpy(str1, "12345678901234567890", sizeof(str1)); 16: printf("strncpy : [%s]\n", str1); 17: }
snprintf : [1234567890]
strncpy : [12345678901]
一瞬、「おお、やってくれるやん」と思ったが、strncpy()では11文字出力されているので、STRMAX+1の後ろに\0がついていることになるな。
まあ、こういうのは、スタックの配置とアラインメントを考えて、こうするのがわかりやすかろう。
01: #include <stdio.h> 02: #include <string.h> 03: 04: #define STRMAX (15) 05: 06: int main(void) 07: { 08: char str0[STRMAX + 1]; 09: char str1[STRMAX + 1]; 10: char str2[STRMAX + 1]; 11: 12: memset(str0, 'x', sizeof(str0)); 13: memset(str2, 'y', sizeof(str2)); 14: 15: memset(str1, 'a', sizeof(str1)); 16: snprintf(str1, sizeof(str1), "12345678901234567890"); 17: printf("snprintf : [%s]\n", str1); 18: 19: memset(str1, 'a', sizeof(str1)); 20: strncpy(str1, "12345678901234567890", sizeof(str1)); 21: printf("strncpy : [%s]\n", str1); 22: }
snprintf : [123456789012345]
strncpy : [1234567890123456yyyyyyyyyyyyyyyy`d�D�]
メモリの配置がどっち側かわからなかったので前後に追加したが、上から順番だったようだ。
strncpy()はstr1に20文字中16文字をコピーし、そのまま\0は付加しなかった。
メモリの境界としてつながっていたので、printf()するとstr2の"yyy..."が出力され、こちらも\0がなかったのでさらに後ろのゴミが出力されて、\0が現れたので止まった、というところだろう。
strncpy()も\0付加してくれていいような気がしたのだけど、余計なことはしないということで付加はしないのだろう。
snprintf()は、そもそもフォーマットという余計なことをするので、\0の付加くらいは当たり前という立場なのか。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。