• ベストアンサー

ptrcpy関数 コピーする領域の確保について

prcrpyを使い、コピーする領域の確保をわざと少なめにしたプログラムを 下のようにかいたのですが、エラーが出ません。 どうしてでしょうか? #include <stdio.h> #include <string.h> main() { char s[5] = "Hello"; printf("%s\n",s); strcpy(s,"Good bye") ; printf("%s\n",s); }

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

VC++2008EEをXPで使っています。 私の環境では少なくとも char s[5] = "Hello"; の時点で初期化子が多すぎますとエラーが出てビルドできませんでした。 次にs[6]にしてみると strcpyがunsafeなのでstrcpy_sを使っておくれとコンパイラが支持してくれました。(設定変更すると特定の警告出さないようにもできますが、私は一応そのままです。) ただ、変更しなくても警告は出るものの実行ファイルの生成自体は成功します。 それでも、strcpy(s,"Good bye"); ということが起きるため、不正終了までしてくれます。 ただ、デバッグで一行ずつ追っていくと、このままではその行ぴったりでコケるような感じではないようです。 もちろん、指示通りstrcpy_sにすれば strcpy_s(s,sizeof s,"Good bye"); の行を実行したときにコケてくれます。 もし大規模アプリケーションを組むことがありましたら、こういったことをしっかりチェックしてくれるコンパイラを採用することをおすすめします♪ ミスした場合にすぐに細かく教えてくれる可能性が高ければ、それだけ完成するコードに信頼感がありますからね。

yuukizx
質問者

お礼

回答ありがとうございます。

その他の回答 (6)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.6

>printf("%s\n",s); s[]に終端'\0'がないため、'\0'を見つけるまで ゴミを吐き出す、という意味では問題あり。

yuukizx
質問者

お礼

回答ありがとうございます。

回答No.5

  >char s[5] = "Hello";    この書き方自体は、問題ない。  

yuukizx
質問者

お礼

回答ありがとうございます。

  • softimage
  • ベストアンサー率61% (68/111)
回答No.4

エラーはコンパイルエラーが出ないということですよね? 実行時のエラーは環境によって出たり出なかったりといったことが あります。 strcpy関数自体が第一引数の型さえ合っていればその先のことまでは チェックしないということではないでしょうか? C言語の便利な面でもあり、使い方を誤ると暴走の一因にもなる怖い 一面でもありますね。

yuukizx
質問者

お礼

回答ありがとうございます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

未定義動作だから, どういう動作であってもおかしくない. エラーが出て止まるかもしれんし, 突然ハードディスクをフォーマットしだすかもしれんし, 鼻歌を歌い出すかもしれん.

yuukizx
質問者

お礼

回答ありがとうございます。

回答No.2

>エラーが出ません。 「segment fault」や「access vioration」のことですか? 上記は「アクセスできない場所」に対してのアクセスで発生するものです。 >char s[5] = "Hello"; 程度の大きさではよほどのことがない限り発生しません。

yuukizx
質問者

お礼

回答ありがとうございます。

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

>エラーが出ません。 >どうしてでしょうか? 破壊した領域に、他の誰もアクセスしようとしていないからです。 破壊してしまった場所に、次にアクセスしようとしたときに 何かよくないことが起きるかもしれません。 ところで、 >char s[5] = "Hello"; s[]の大きさが1バイト足りないことは理解できていますね?

yuukizx
質問者

お礼

>s[]の大きさが1バイト足りないことは理解できていますね? はい。 回答ありがとうございます。

関連するQ&A

  • 配列について

    初歩的な質問ですいませんが、質問よろしくお願いします。 ◎1----------------------------- #include<stdio.h> int main(void) { char ss[10]="AB"; printf("ss=%s\n",ss); return 0; } ------------------------------------ ◎2-------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss[0]='A'; ss[1]='B'; ss[2]=0; printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎3------------------------------- #include<stdio.h> #include<string.h> int main(void) { char ss[10]; strcpy(ss,"AB"); printf("ss=%s\n",ss); return 0; } ----------------------------------- ◎4------------------------------- #include<stdio.h> int main(void) { char ss[10]; ss="AB"; printf("ss=%s\n",ss); return 0; } ---------------------------------- 以上4つのプログラムで、◎2と◎3は正常に動くと理解できたのですが、何故、◎1は正常に動き、◎4は「'const char [3]' から 'char [10]' に変換できません。」といったようなエラーが出てしまうか分かりません。 教えていただければ嬉しいです。

  • 構造体の型について

    ある構造体をxxxと名づける以下のプログラムを作成しました。 ーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx aaa; strcpy(aaa.variable,"bbb"); printf("%s\n",aaa.variable); } ーーーーーーーーーーー これは動き、bbbと表示されます。 しかしながら、構造体のポインタを使用した 以下のプログラムではコンパイルはとおりますが実行時にコアダンプして落ち ます。 ーーーーーーーーーーーーーーーーーーーー #include <stdio.h> #include <string.h> main() { typedef struct { char variable[64]; char type[64]; char value[512]; } xxx; xxx* aaa; strcpy(aaa->variable,"bbb"); printf("%s\n",aaa->variable); } ーーーーーーーーーーーーーーーーーーーーーーー 両プログラムの意図はまったく同じなのに何故いけないのでしょうか。

  • NULL領域を読み書きするの意味が?

    C言語の初学者です。 コンパイラは、Borland C++ 5.5.1 for Win32 を使っています。 たまたま見つけた C magazine プログラミングの禁じ手Web版 C言語編で、「NULL領域を読み書きする」という個所があり、下記ソースで発覚すると掲載されていました。 (http://www.cmagazine.jp/src/kinjite/c/null.html#index5) void f() { static char *theTxt; strcpy(theTxt,"TEST\n"); printf("%s",theTxt); } 自分の環境で、下記のソースで動かしてみたところ、アプリケーションエラーになりました。 #include <stdio.h> #include <string.h> int main(void) { static char *theTxt; /* (1) */ strcpy(theTxt,"TEST\n"); printf("%s",theTxt); return 0; } この禁じ手の意味そのものが、全く理解できませんでした。 ・NULL領域というのは、(1)のstatic定義されたポインタことをさしているのか? ・(1)の static をつけないで実行すると、正常終了したので、static の領域に書き込んではいけないのか? (そんなことはないと思うのだが)

  • 領域の開放がされているかどうかはどうやって調べればいいのでしょう。

    #include <stdio.h> #include <stdlib.h> int main(void){ char *str; printf("&str : %d\n", &str); // ●領域割り当て前のアドレス(NULL) printf("str : %d\n", str); str = (char *)calloc(15, sizeof(char)); // (1)領域割り当て後のアドレス printf("str : %d\n", str); // str領域開放 free(str); // (2)領域解放後のアドレス printf("str : %d\n", str); return 1; } 開放した後は●と同じくNULLになると思っていたのですが、 実際に実験してみて(1)と(2)のアドレスが同じものでした。 アドレスは割り当てたままに見えますが、実際にはちゃんと開放されているのでしょうか? それとも、何か間違えているでしょうか。 よろしくお願いします。

  • 文字列のコピー

    C言語で、文字列をコピーする関数で、処理が止まってしまいます。 以下が実行したプログラムです。 #include<stdio.h> #include<string.h> void copy(char *str2 ,char *str3){ strcpy(str2,str3); } void input(char* str){ scanf("%s",str); } int main (void){ char *a; char *b="TEST"; printf("%s\n",b); input(a); copy(b,a); printf("%s",b); return(0);} copy(b,a);で処理が止まってしまいます。入力した文字列を表示できるように、御指摘お願いします。

  • ライブラリ関数

    文字列をコピーする(strcpy) 文字列の長さを調べる(strlen) 配列の長さを調べる(sizeof) #include <stdio.h> #include <string.h> int main(void) { char s1[128] = "ABCD"; char s2[128] = "EFGH"; char s3[128] = "IJKL"; strcpy(s2, s1); strcpy(s3, s2); puts("s1をs2にs2をs3にコピーしました。"); printf("s1 = %s\n", s1); printf("s2 = %s\n", s2); printf("s3 = %s\n", s3); printf("文字列%sの長さは%uです。\n",s3,(unsigned)strlen(s3)); printf("文字列%sの長さは%uです。\n",s3,strlen(s3)); return (0); } char *strcpy(char *d, const char *s) { while (*d++ = *s++) printf("pointer=%s \n",d); } /* 文字列sをdにコピーする[配列版] */ char *strcpy(char d2[], const char s2[]) { unsigned i=0; while (d2[i] = s2[i]){ i++; printf("hairetsu=%s\n",&d2[i]); } } /*--- 文字列strの長さを返す[ポインタ版] ---*/ size_t strlen(const char *s) { size_t len = 0; while (*s++) len++; return (len); } /*--- 文字列strの長さを返す[配列版] ---*/ unsigned strlen(const char str[]) { unsigned len = 0; while (str[len]) len++; return (len); } c:\program files\microsoft visual studio 8\vc\include\string.h(73) : 'strcpy' の宣言を確認してください。 メッセージ: 'This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.' c:\program files\microsoft visual studio 8\vc\include\string.h(73) : 'strcpy' の宣言を確認してください。 メッセージ: 'This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.' c:\documents and settings\owner\my documents\visual studio 2005\projects\test8-3\test8-3\test8-3.c(48) : error C2084: 関数 'char *strcpy(char *,const char *)' は既に本体を持っています。 c:\program files\microsoft visual studio 8\vc\include\string.h(73) : 'strcpy' の前の定義を確認してください c:\documents and settings\owner\my documents\visual studio 2005\projects\test8-3\test8-3\test8-3.c(68) : error C2084: 関数 'size_t strlen(const char *)' は既に本体を持っています。 c:\program files\microsoft visual studio 8\vc\include\string.h(80) : 'strlen' の前の定義を確認してください 上記の問題が解決できません。助けてください><

  • strncpy後のatoiがおかしい

    こんにちは。 C++をVS2005でやっています。 atoi関数を使っているんですが、10個の配列strにstrncpyをやると値がおかしくなります。 10個目に'\0'を代入させてやってみても駄目でした。 以下にソースを載せます。 #include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> int main( void ) { char string[256]; char str[10]; char *moji = "12345464"; int l; // using template versions of strcpy_s and strcat_s: strcpy(string, "6877897898"); strcat(string, "strcpy_s"); strcat(string, "and"); // of course we can supply the size explicitly if we want to: strcat(string, "strcat_s!"); strncpy(str, string, 10); l = strtol(str,NULL,10);// 値が違う 6877897898にならない printf("str = %d\n", l); l = atoi(moji); printf("moji = %d\n", l); l = atoi(string);// 値が違う printf("string = %d\n", l); printf("String = %s\n", string); getchar(); return 0; } 表示結果 str = 2147483647 moji = 12345464 string = 2147483647 String = 6877897898 mojiは正常に動作しますから、ナル文字が原因なのかと思ってしまいますが。原因がいまいち分かりません。 よろしくお願いします。

  • 乱数を使って

    プログラム #include<stdio.h> #include<string.h> #include<stdlib.h> main() { char land[10][10]; int i, j; for(i=0; i<10; i++) { for(j=0; j<10; j++) { strcpy( &land[i][j], "□"); printf("%s",&land[i][j]); } printf("\n"); } } で発生させた10×10の□の上に、 乱数を使って■を25個上書きしたいのですが、 どうしたらできるか教えてください。

  • string.h とかって何?

    #include で最初に含むファイルっていったい何者なんでしょうか? rand()を使うにはstdlib.hをインクルードしますし、printfのような入出力関係にはstdio.hを、文字関係ならstring.hを・・。 それはわかるのですが、これは、それぞれのヘッダファイルに自作関数の集合のようなものが入っていると考えるのは間違いなんでしょうか? 例えば、strcpyを使用するにはstring.hをインクルードするべきですが、 それはstring.hの中に char *strcpy(char *s1, const char *s2) {   char *p = s1;   while (*s1++ = *s2++)     ;   return (p); } みたいな記述が入っていると想像するのは間違いですか? 自作関数を集めてヘッダファイルにする事出来ますけど、これらは違うんですか? これだとprintfとかどうやって実装しているんだって思ってしまって・・。 直接stdio.hを開いてみたものの意味不明で、其の中にさらにある.hファイルも開いてみましたがよくわかりませんでした・・。 すみませんが、よろしくお願いします><

  • char型ポインタ

    よくプログラムで charポインタだけ指定して、 #include<stdio.h> int main(){ char* p; p = "abcdef"; printf("%s",p); return 0; } のようにしているのをみかけますが、 メモリーを確保していなくても問題ないのでしょうか? char* p; p = (char*)malloc(7); strcpy(p,"abcdef"); としたのと同じでしょうか?

専門家に質問してみよう