ベストアンサー ※ ChatGPTを利用し、要約された質問です(原文:自動変数の有効範囲について) 自動変数の有効範囲とは?仕組みと注意点 2010/08/02 17:31 このQ&Aのポイント 自動変数の有効範囲とは、変数が有効な範囲を指す言葉です。変数が宣言されたブロック内でのみ有効であり、ブロックを抜けると自動的にメモリが解放されます。プログラム中でchar *strを使った場合、その有効範囲は関数内でのみ有効です。しかし、ポインタの指す先を文字列リテラルとして指定すると、そのメモリはプログラム全体で共有されるため、別の場所からでも参照が可能です。char *を返したい場合はmallocを使って動的にメモリを確保し、そのポインタを返すことが一般的です。返されたポインタを使用した後は必ず解放する必要があります。 自動変数の有効範囲について 自動変数の有効範囲について 以下のプログラムではchar *strの有効範囲はsub()内だけだと思ったのですが、意図せず main内でputs()した場合に"abc"が表示されてしまいます。 これはたまたまメモリ上にデータが残っていただけなのでしょうか? 因みにchar str[100]と宣言すると、意図したとおりコンパイルでもwarnningがでてゴミが出力されます。 また一般的にはchar *を返したい場合にはどうしたらいいのでしょうか? mallocして返すのでしょうか? 以上よろしくお願いします -------------------------------------- #include <stdio.h> char *sub(); int main() { char *q; q = sub(); printf("%s\n",q); } char *sub() { char *str = "abc"; return str; } 質問の原文を閉じる 質問の原文を表示する みんなの回答 (3) 専門家の回答 質問者が選んだベストアンサー ベストアンサー Tacosan ベストアンサー率23% (3656/15482) 2010/08/02 17:48 回答No.1 文字列リテラルが「static な文字配列」であることを理解していれば, 「たまたま」ではなく「必然」であるとわかる. 質問者 お礼 2010/08/02 22:24 なるほど!!。 的確かつ明快な回答ありがとうございました。 staticな文字列であるから関数の範囲を超えてアドレスが維持されていたのですね。 ありがとうございました。 広告を見て全文表示する ログインすると、全ての回答が全文表示されます。 通報する ありがとう 0 その他の回答 (2) asuncion ベストアンサー率33% (2127/6290) 2010/08/02 20:57 回答No.3 そのコードが意図しない結果を招くのであれば、 下のコードも意図しない結果を招くことになります。 実際はどうですか? #include <stdio.h> int sub(void); int main(void) { int a; a = sub(); printf("%d\n", a); return 0; } int sub(void) { int n; n = 12345; return n; } 質問者 補足 2010/08/02 22:29 すいません。言葉足らずでした。 このコードですと値が返ってしまうため、sub()内のnとmain()内のaはアドレスが違ってしまいますよね。 ポインタを返しているのに、なぜその値が静的変数でもないのに関数を超えて維持されているのかがわかりませんでした。 別回答を頂いた方から文字列リテラルはstaticであると教えていただいて謎が氷解しました。 広告を見て全文表示する ログインすると、全ての回答が全文表示されます。 通報する ありがとう 0 noname#116548 2010/08/02 17:52 回答No.2 何処がおかしいのかな? *strに"abc"のポインタを入れてmainに返す。 そのポインタの示すアドレスの文字列を表示する。 ?何をしたいのかな… 質問者 補足 2010/08/02 22:30 言葉足らずですいませんでした。 ポインタを返しているのに、関数ブロックを越えてアドレスが維持されているのが理解できなかったんです。 説明不足ですいませんでした。 広告を見て全文表示する ログインすると、全ての回答が全文表示されます。 通報する ありがとう 0 カテゴリ [技術者向] コンピュータープログラミング・開発C・C++・C# 関連するQ&A C言語のint型の配列が分かりません #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名)); はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか? int とcharの使い方と違い 教えてgooに投稿するのは初めてですがよろしくお願いします。 最近C言語を勉強し始めた初心者です。 ネットのサイトを見て独学でしています。 過去スレッドをさらっと見て聞きたいことが書いてなかったので投稿します。(同じスレッドがあったらすみませんOTL) #include<stdio.h> int main(void) { int str='a'; printf("str=%c\n",str); return0; } この上のプログラムでは str=a と出て、エラーが出ずにコンパイル出来ました。でも、 #include<stdio.h> int main(void) { int str[]="abc"; printf("str=%s\n",str); return0; } とするとエラーが出ます。 int とcharの使い方と違いについて詳しく教えてほしいです>< お願いします。 C言語について #include <stdio.h> int main(void) { printf("123456\tABC DEFGHIJK\n"); printf("2006/4/14\n"); printf("programing\n"); } のprintfをすべてputsに書き換えてコンパイル・実行すると、 #include <stdio.h> int main(void) { puts("123456\tABC DEFGHIJK\n"); puts("2006/4/14\n"); puts("programing\n"); } になると思うんですけど、そのputsを用いて上のprintfを用いたプログラムと同じ出力を得るにはどのようなプログラムに変えればいいのでしょうか? ネットワークエンジニアとは?技術職の未来を考える OKWAVE コラム 修正おねがいします。 コンパイルして得られる実行ファイルを list1 として、 %list1 文字列1 文字列2 ・・・ を実行すると文字列1、文字列2、・・・を連結した一つの文字列を動的に生成した領域に格納し、それをディスプレイ上に表示するプログラムを作成しようと思います。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc,char *argv[]) { char s[50]; int n = 0; int count = 0; char *str; if(argc < 2) puts("連結できませんでした"); else{ for(n = 1; n < argc; n++) { str = argv[n]; for(;*str != '\0'; count++) { s[count] = *str; str++; } } } s[count] = '\0'; str = malloc(strlen(s) + 1); if(str != NULL){ strcpy(str, s); printf("%s\n", s); free(str); } } これでは実行できません。どこをどう修正すべきでしょうか? また、まったく違うのであれば正しいのを教えてください。 すいません。よろしくお願いします。 ポインタで分からないことがあります。 つい最近C言語の勉強を始め、現在ポインタの勉強をしています。 過去の質問を検索したり、サイトを見てみましたが、一人の力では解決できませんでしたので質問させていただきます。 ポインタのプログラムで、下記のプログラムについて分からないことがありました。 ――――――――――――――――――――――――――――――――― #include <stdio.h> int main (void) { char *str = "abc"; printf ("%s %d %d\n", str, &str, &(*str)); str = "日本語"; printf ("%s %d %d\n", str, &str, &(*str)); return 0; } ――――――――――――――――――――――――――――――――― このプログラムで、「char *str = "abc";」の部分でstrには abcのアドレスが入っていると思っていたのですが、 1度目の「printf ("%s %d %d\n", str, &str, &(*str));」で、 結果が「abc 1245064 4235560」となっているのを見ると 私の見解は間違っている気がします。 「char *str = "abc";」の部分では一体なにが行われているのでしょうか? また、このプログラムをコンパイルして実行した結果が、 abc 1245064 4235560 日本語 1245064 4235574 となったのですが、なぜstrのアドレスは同じなのに、 &(*str)のアドレスは異なるのでしょうか? 質問をまとめますと、以下の2つです。 1.「char *str = "abc";」の部分では一体なにが行われているのでしょうか? 2.「abc」と「日本語」のstrのアドレスは同じなのに、&(*str)のアドレスは異なるのでしょうか? 初心者ですので言葉の足らない部分があるかもしれませんが、ご教授のほどよろしくおねがいします。 c言語の問題 以下のプログラムをコンパイルし、実行したところ、次のような画面が表示された。下記の関数定義部分を補いなさい。 gcc test.c ./a.out abc def answer = defabc 以下ソースコード #include<stdio.h> void stradd(char A[], char B[]); int main(){ char str1[100], str2[100]; scanf("%s", str1); scanf("%s", str2); stradd(str1, str2); printf("answer = %s\n", str2); } void stradd(char A[], char B[]){ } よろしくお願いします。 atoi 123と表示されたいんだけど、コンパイルエラーです。 この場合、atoiの引数して、str[3]の文字を入れる変数をもう1つ用意するしかないですか? キャストでうまくできる方法があったら教えてください。 strという変数の"abc123"という文字は変化させたくないんです。 #include <iostream.h> main(){ int i; char str[] = "abc123"; i = atoi(str[3]); printf("%d\n", i); } mallocで引数に変数を入れると警告がでます #include<stdio.h> int main(void){ int n,i; int* array; puts("n=?"); scanf("%d",&n); array = (int*)malloc(sizeof(int) * n); for(i=0;i<n;i++) *(array+i) = i; for(i=0;i<n;i++) printf("%d ",*(array+i)); puts(""); return 0; } C言語で、上述のプログラムをコンパイルしたところ、 9: warning: incompatible implicit declaration of built-in function ‘malloc’ と警告がでます。 ./a.outで普通に実行できるのですが、 警告がでるということは、もっと正しいやり方があるということでしょうか? [C]char型のダブルポインタ 粗雑で申し訳ありませんが、 以下のソースをコンパイルできましたが、 うまく実行できません。 自分なりに間違いがないと思うのですが、 間違い等をご指摘頂ければ助かります。 #include <stdio.h> void func(char **ptr) ptr[][10] か (*ptr)[] なら通る *ptr[] は通らない { printf("----- func -----"); printf("%s\n", *ptr); printf("%c\n", **ptr); putchar('\n'); } int main(void) { char str[5][10] = {"AAAAA", *str[] にすると func で **ptr で通る "BBBBB", "CCCCC", "DDDDD", "EEEEE", }; printf("----- main -----"); printf("%s\n", *str); printf("%c\n", **str); putchar('\n'); func(str); return (0); } 実行結果 ----- main ----- AAAAA A ----- func ----- Bus error (core dump) 関数への受け渡しで、型が違うというお叱りを受けますが、 コンパイルはできました。 コンパイラはCCです。 ではよろしくお願いします。 教えてください!! 文字を入力する。例えば、DFGHJ。次に番号を入力して、その番号に示された値を表示。ここでは、2が入力されれば、Fを表示するのですが、分かりません。 考えてみたのですが、コンパイルエラーで、出来ません。教えてください。宜しくお願いします。 #include <stdio.h> int main(void) { char str[6], no; printf("文字を入力する", str); scanf("%s", str); printf("番号を入力:"); scanf("%d", &no); switch(no,str[]) { case 0 : puts("%d番目は%sです",no, str[0]); break; case 1 : puts("%d番目は%sです",no, str[1]); break; case 2 : puts("%d番目は%sです",no, str[2]); break; case 3 : puts("%d番目は%sです",no, str[3]); break; case 4 : puts("%d番目は%sです",no, str[4]); break; case 5 : puts("%d番目は%sです",no, str[5]); break; } return(0); } メソッド間の文字列の受け渡し 初歩的な内容ですが、混乱してしまっているので、どなたか教えてください。 呼び元のメソッドで文字列を設定した文字列を呼び先subで取り出したいのですが、 アドレスから文字列を取り出すにはどうすればいいのでしょうか? #include <stdio.h> main() { char abc[]="ABC"; printf("%s\n", abc); sub(abc); /* 文字列abcのアドレスを値渡し */ printf("%s\n", abc); } sub(char *abc) /* 文字列abcのアドレスをポインタとして値受け取り */ { } mallocがうまく動かない コマンドライン引数で指定された文字列を逆順に返すプログラムを作るため 下記のようなプログラムを組みました。 ところが変数strの大きさがargv[1]より大きくなってしまいます。 どうすればよいのでしょうか。 #include <stdio.h> #include <stdlib.h> char *mstrrev (char *s); int main(int argc, char *argv[]){ char *str; str = mstrrev(*(argv+1)); printf("%s",str); free(str); } char *mstrrev (char *s){ int length,i; char *str; for(length=0;*(s+length)!='\0';length++); str = (char *)malloc(sizeof(char)*length); for(i=0;i<length;i++){ str[i] = s[length-1-i]; } return str; } AIは使う人の年齢や市場にも影響する?人工知能の可能性 OKWAVE コラム 文字列、ポインタを使用したプログラムで分からないところがあります 1 #include <stdio.h> 2 3 void setstr(char *str){ 4 str = "abc"; 5 return; 6 } 7 8 int main(){ 9 10 char *str; 11 12 setstr(str); 13 14 str[1] = 'E'; 15 16 printf("str = %s\n", str); 17 18 return 0; 19 } 20 上記のプログラムの動きがいまいち理解できません。 (メモリの状態など) 16行目でprintfすると、結果は「str = 、E・」となります。 ---まず、4行目でabcに対してメモリが確保されて、その先頭アドレスが strに設定されます。 しかし、setstr関数を抜けた時点で、先ほど確保されたメモリは開放されて しまう。(? ここは想像です。確証がありません) main関数に戻ってきて、14行目で変更しているメモリは、abcがかつてあった 場所の"b"の部分。(str自体は何も変更されていないから) 16行目でprintfしているのだけど、なぜこの結果になるのかが分かりません。。 分かる方いましたら教えて下さい。上の文章では何を言っているのか分かりづらいとは 思いますが。。 説明には適宜行番号を使って頂いて構いません。 よろしくお願いします。 分割コンパイルの方法がわかりません‥(Studio.NET) mainとsubという2つのcppファイルと各ヘッダファイルで分割コンパイルを試みましたがうまくいきません・・。 何が間違っているのでしょう・・。 エラーメッセージ error LNK2005: "char * a" (?a@@3PADA)は既にmain.objで定義されています。 fatal error LNK1169: 1つ以上の複数回定義されているシンボルが見つかりました。 と表示されます。ファイルソースは以下です。どなたか教えてください>< ----------(main.h)---------- char a[100]; ----------(main.cpp)---------- #include<stdio.h> #include "main.h" #include "sub.h" int main(){ sprintf(a,"hello."); sub_write(); return 0; } -----------(sub.h)----------- void sub_write(); -----------(sub.cpp)------------- #include <stdio.h> #include "main.h" #include "sub.h" void sab(){ printf("%s\n",a); } return; } C言語 ナル文字の表示 '\0'(ナル文字)を表示させたいのですがどうすればできますか? str[3] = となって何も表示されません。 str[3] = \0 とはならないんでしょうか? ---プログラム---------------------------- //ナル文字の表示 #include <stdio.h> int main(void){ char str[5] = "abc"; printf("str[0] = %c\n", str[0]); printf("str[1] = %c\n", str[1]); printf("str[2] = %c\n", str[2]); printf("str[3] = %c\n", str[3]); printf("str[4] = %c\n", str[4]); return 0; } ---------------------------- ----実行結果----------------- str[0] = a str[1] = b str[2] = c str[3] = str[4] = ------------------------------------ 文字列を関数に渡すぷろぐらむなのですがおかしいです。 <ソース> #include<stdio.h> #include<stdlib.h> void str(char a[]); int main() { char st[10]="abcde"; str(st); str("ABCabc123"); return 0; } void str(char a[]) { int i; printf("%s\n",a); i=0; while(a[i]){ a[i]=toupper(a[i]); putchar(a[i]); i++; } putchar('\n'); } 分からないところがあるので質問します。 toupperは、大文字にするんですよね。 putcharは、基本的にchar型でしたっけ? putsとgetsは、int型でしたっけ? 後、プログラムが暴走してます。 どこがおかしいんでしょう? ポインタ配列の動的確保 ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char)); ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。 ポインタの問題です 学校の課題である文字列をポインタを使って逆順に表示するというプログラムを作ったのですが、「問題で引数で与えられた文字列を逆順とする関数を作成せよ.ただし文字数が最大256文字であると仮定して良い.」ということなんですが、課題が求めている答えと自分が作ったプログラムがあっているか確認お願いします。 #include <stdio.h> void reverseWord(char *str); void main(void) { char *str = "sapporo"; char *p, *q; printf("元: %s\n", str); p = q = str; while (*q != '\0') q++; printf("逆順:"); while (q >= p) putchar(*q--); printf("\n"); } よろしくお願いします。 abcdとキーボードで打ったらdcbaと表示されるプログラム C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } } constの位置 申し訳ありませんが、続けて質問させていただきます。 char const と const char は同じ意味でしょうか。 次のプログラムは配列をconst charと宣言しています。 ary[1]='N'; の行で、意図した通りにコンパイルエラーになります。 これはchar constと宣言しても、同じ意味なんでしょうか。 #include <stdio.h> int main(void) { const char ary[ ] = { 'A', 'B', 'C', '\0' }; ary[1] = 'N'; printf("aryは%s\n", ary ); return 0; } また、 const int a=1; int const a=1; この2つは同じ意味でしょうか。 注目のQ&A 「You」や「I」が入った曲といえば? Part2 結婚について考えていない大学生の彼氏について 関東の方に聞きたいです 大阪万博について 駅の清涼飲料水自販機 不倫の慰謝料の請求について 新型コロナウイルスがもたらした功績について教えて 旧姓を使う理由。 回復メディアの保存方法 好きな人を諦める方法 小諸市(長野県)在住でスキーやスノボをする方の用具 カテゴリ [技術者向] コンピューター プログラミング・開発 Microsoft ASPC・C++・C#CGIJavaJavaScriptPerlPHPVisual BasicHTMLXMLCSSFlashAJAXRubySwiftPythonパフォーマンス・チューニングオープンソース開発SEOスマートフォンアプリ開発その他(プログラミング・開発) カテゴリ一覧を見る OKWAVE コラム 突然のトラブル?プリンター・メール・LINE編 携帯料金を賢く見直す!格安SIMと端末選びのポイントは? 友達って必要?友情って何だろう 大震災時の現実とは?私たちができる備え 「結婚相談所は恥ずかしい」は時代遅れ!負け組の誤解と出会いの掴み方 あなたにピッタリな商品が見つかる! OKWAVE セレクト コスメ化粧品 化粧水・クレンジングなど 健康食品・サプリ コンブチャなど バス用品 入浴剤・アミノ酸シャンプーなど スマホアプリ マッチングアプリなど ヘアケア 白髪染めヘアカラーなど インターネット回線 プロバイダ、光回線など
お礼
なるほど!!。 的確かつ明快な回答ありがとうございました。 staticな文字列であるから関数の範囲を超えてアドレスが維持されていたのですね。 ありがとうございました。