掲示板 |
掲示板を置いてみました。ご自由に書き込んで下さい。 ただし、私は根性なしなので、閑古鳥が鳴いたり、荒れてきたと 思ったらとっとと閉鎖する可能性があります。 |
100 | Re^2: sprintf()、私も「単に知らない」に一票。 | コメント数: 0件 |
レプラコーン | sailis@annie.ne.jp | 2001/08/28 (火) 19:25 | |
http://www.annie.ne.jp/~sailis/pvon/ | ||
> 文字派ってのがいますぜ。こんなの。 まさに文字派ですね。ネタじゃないですよね? この例の場合、printf()もマトモに使えてませんね・・・。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
99 | Re^2: 「入門書に書いてあった」に一票 | コメント数: 0件 |
レプラコーン | sailis@annie.ne.jp | 2001/08/28 (火) 19:20 | |
http://www.annie.ne.jp/~sailis/pvon/ | ||
勘違いってやつですね。 微笑ましいというかなんと言うか・・・。 文字を16進で書くのも多いですけど、 通信コードも16進数で書く人も多いですよね。 #defineして欲しいです。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
98 | 正誤表の誤? | コメント数: 1件 |
costa | 2001/08/28 (火) 15:11 | |
ポインタ制覇の正誤表に関して、p228で抜けていたのはstring.hの 方だと思います. |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
97 | Re: sprintf()、私も「単に知らない」に一票。 | コメント数: 1件 |
REC | tabe@mug.biglobe.ne.jp | 2001/08/27 (月) 23:15 | |
http://ncosweb.h2o-lp.co.jp | ||
文章派:sprintf() 単語派:strcat() とすると、 文字派ってのがいますぜ。こんなの。 int main() { char w1[20] = {'n','a,',n',d','e',j','i','b','u','n','w','o',' 'k','u','r','u',s','i','m','e','r','u','\0'} ; char strings[128]; ; sprintf(buf,"%d\0",sizeof(w1)) ; /* この人達は必ず¥0を自分で書く*/ /* で、sprintfを知らないわけでもない */ sprinft(strings,"%s は %s 文字数",w1,buf) ; printf(strings) ; } /* ふーーーー生産性バッチシ */ > strcat()派については何度か考えたことがあるのですが、 > どうも文字列を全体的に見れないで、 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
96 | Re: 「入門書に書いてあった」に一票 | コメント数: 12件 |
REC | tabe@mug.biglobe.ne.jp | 2001/08/27 (月) 22:42 | |
http://ncosweb.h2o-lp.co.jp | ||
もっと、かわいいの知ってる。 if('0x41' <= ch <= '0x5A') { ★ダブルで、お楽しみください。 > > if ((ch >= '0') && (ch <= '9')) { > > まだ、かわいい(^^;) > if((ch >= 0x41) && (ch <= 0x5A)) { > なんてのもいるし。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
95 | 「入門書に書いてあった」に一票 | コメント数: 13件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/08/27 (月) 08:52 | |
記憶が定かではないのですが、昔読んだ入門書にstrcat()でゴリゴリ文字列を 連結する方法が書いてありました(本のタイトル・作者などは失念) そういう本を参考にしながらプログラミングしたのでは? しまった買っておけばよかった。残念(^^;) その後、一切勉強しないところがすごいのですが。 まぁ、そういう意味では「単に知らない」ってことですけど。 > if ((ch >= '0') && (ch <= '9')) { まだ、かわいい(^^;) if((ch >= 0x41) && (ch <= 0x5A)) { なんてのもいるし。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
94 | sprintf()、私も「単に知らない」に一票。 | コメント数: 18件 |
レプラコーン | sailis@annie.ne.jp | 2001/08/27 (月) 05:00 | |
http://www.annie.ne.jp/~sailis/pvon/ | ||
同様にsscanf()も、です。 strcat()派については何度か考えたことがあるのですが、 どうも文字列を全体的に見れないで、 思考の赴くままにソースを書いているからのようです。 あきらかにゴリ押しプログラマですね。 またsprintf()を教えても「フォーマット文字列が苦手で」 などと言って譲らない人も・・・;-< 他に、実際にいくつかの会社をソースコードを見て思ったのは、 文字分類関数(is〜関数)を使わない人が多いことですね。 if ((ch >= '0') && (ch <= '9')) { ... } というコードを各所に書いていたりします。 複数の文字セットを意識する場合は ロケールなどに気をつけなければならないですが。 更に細かいところをつつけば、abs()とかfabs()などの算術関数とか、 memcpy()で領域を上書きするから捨てバッファを使う、なんて人 (memmove()を使えば・・・)もいますね。 前橋さん、業界のためにANSIライブラリ・ポケットリファレンスを作るしか。 # "プログラミング言語C"にはリファレンスがついてますが、 # 参照しづらいフォーマットですし、 # "標準Cライブラリ"は推薦しても「厚過ぎる」ってみんな引きますしね。:-) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
93 | Re^6: 体当たりP255宿題(解決) | コメント数: 0件 |
ミントレ | mifiosan@yabumi.com | 2001/08/18 (土) 03:09 | |
*input_string(FILE *fp)と同様の関数を作成し、そこにtokenを送って、ポインタを得ることで無事解決できました。やはり->を使い慣れていなかったのが最大の原因です。どうも*がないと、配列のように思えてしまいます。 お陰で、大分理解が進んだように思います。 アドバイス誠にありがとうございました。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
92 | Re^5: 体当たりP255宿題(その後) | コメント数: 1件 |
(ぱ) | maebashi@cse.co.jp | 2001/08/15 (水) 18:44 | |
> これで、いわゆるscanfの食べ残しはなくなったのですが、 >読出し後、蔵書一覧を開くと文字化けしてしまいます。 ... > 何が、原因なのでしょうか? これは当然の結果です。 data_p->book_nameなどのポインタが、いったいどこを指して いるのかをはっきり認識する必要があるのではないかと。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
91 | Re^4: 体当たりP255宿題(その後) | コメント数: 2件 |
ミントレ | mifiosan@yabumi.com | 2001/08/15 (水) 03:10 | |
結局、scanfは、あとあと面倒そうなので、fgets でcsvファイルをchar bufinに読みこんだ後、 /*GET_token ルーチン*/ void getting_token(char bufin[1024],Adress *data_p) { char *token; token=strtok(bufin,",");data_p->book_name=token; token=strtok(NULL,",");data_p->author=token; token=strtok(NULL,",");data_p->publisher=token; data_p->price=atoi(strtok(NULL,",")); token=strtok(NULL,",");data_p->isbn=token; token=strtok(NULL,",");data_p->note=token; } でtokenを取り出す方式を採る事としました。 これで、いわゆるscanfの食べ残しはなくなったのですが、読出し後、蔵書一覧を開くと文字化けしてしまいます。 ちなみに、上記の各行の後にprintf("%s",data_p->book_name);を入れて実効すると正しく表示されております。 もちろん、一覧処理、データ表示処理の記述はオリジナルのままです。 何が、原因なのでしょうか? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
90 | Re^2: 体当たりP255宿題 | コメント数: 3件 |
ミントレ | 2001/08/11 (土) 16:24 | |
レス有難うございます。 printfすると、やはり、食べ残しがあります。 構造体→ファイル→構造体 で、バックアップとリストアのできる蔵書管理にしたかった のですが、scanf()は、問題ありそうです。 もう少し勉強してみます。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
89 | Re: 体当たりP255宿題 | コメント数: 4件 |
(ぱ) | maebashi@cse.co.jp | 2001/08/09 (木) 20:18 | |
http://member.nifty.ne.jp/maebashi/ | ||
> txtファイルをfopenして、ポインタを獲得し(in_fp)、while((fscanf(in_fp,〜!=EOF))の繰り返しループのなかにfscanfで読みこんでいくことを考えています。 状況はよくわかりませんが、fscanf()は、scanf()と同様、 書式に合わない入力が来たときにはそれを食べ残しますから、 無限ループになるのはおそらくそのせいでしょう。 scanf()の問題点については、本の中にも書いたつもりです。 もしかして、ひとつのfscanf()で、本一冊分のデータをまるごと 読み込もうとしてます? 原理的には無理ではないですが、デバッグの手間を考えても得策では ないでしょう。printf()デバッグしようにも、挟むところも ありゃしないわけで。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
88 | 体当たりP255宿題 | コメント数: 5件 |
ミントレ | mifiosan@yabumi.com | 2001/08/09 (木) 01:20 | |
「体当たり」P255の宿題となっている蔵書管理の保存機能ですが、 for(out=grobal_header;out!=NULL;out=out->next) { fprintf(out_fp,"%s\n",out->book_name); 以下、省略 で、txtファイルに書き出すことは出来たのですが、読み出すことがどうしてもうまく出来ません。 txtファイルをfopenして、ポインタを獲得し(in_fp)、while((fscanf(in_fp,〜!=EOF))の繰り返しループのなかにfscanfで読みこんでいくことを考えています。 しかしながら、繰り返し条件や引数をいじっても、以下のいずれかのモードが出てしまいます。 1.一回でループアウトしてしまう。 2.無限ループにはまってしまう。 3.fscanfで、読みこんだ内容が、つながってしまい、異常終了してしまいます。 そもそも、fscanfを用いるのが間違っているのか、fgetc,fgetsでは、どのように構造体に格納すべきか見当がつきません。ヒントを頂けないでしょうか。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
87 | Re: 本の感想など | コメント数: 0件 |
(ぱ) | maebashi@cse.co.jp | 2001/08/08 (水) 19:10 | |
http://member.nifty.ne.jp/maebashi/ | ||
> ところでポインタ制覇のP67get_word.cの中のlenなんですが、 > 0を2回代入していることに何か特別な意味はあるのでしょうか。 すみません、単なるポカです。 # バグというわけではないと思いますが... 近いうちに正誤表に載せようと思います。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
86 | 本の 感想など | コメント数: 1件 |
costa | 2001/08/07 (火) 14:59 | |
C言語を学習する上で2冊とも大変参考になりとても感謝しています。 (そのかいあってか単位はとれそうです) これからも学習を続けたいと思いますが、もし参考文献以外に何かお勧め の本とかあれば是非教えてもらいたいです。 ところでポインタ制覇のP67get_word.cの中のlenなんですが、 0を2回代入していることに何か特別な意味はあるのでしょうか。 UNIX gccではなかったのですが、windows borlandの時 警告っぽく 表示されたので。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
85 | Re^4: 質問4:うまくいかないint_to_strについて | コメント数: 0件 |
D.Matsu | dmatsu@gld.mmtr.or.jp | 2001/07/18 (水) 13:26 | |
補足、と言うか間違いの訂正を。 > > char *ptr1 = str1; > > char *ptr2 = str2; > > この部分は冗長ですね。 charポインタptr1,2の宣言は必要ですね。 #str1,2が不要、という話だったのですが勢いでやってしまいました(汗) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
84 | Re^2: ”C言語 体当たり学習(徹底入門)”のmy_splitについて | コメント数: 0件 |
(ぱ) | maebashi@cse.co.jp | 2001/07/18 (水) 12:53 | |
http://member.nifty.ne.jp/maebashi/ | ||
ご指摘ありがとうございます。 > ところが、ダウンロードしたースでは、 > #define OUT_FILE_SIZE 140000 となっているため、 > 2MBのファイルを分割した場合、15個のファイルを作ろうとします。 すみません、テスト用にちょっとサイズを小さくしたものを 上げてしまったようです。 帰宅したら修正しておきます。ご迷惑をおかけしました。 > このプログラムは、ファイル名の生成方法に問題があり、 まあ、テストプログラムですから、ファイルの数が10を超えた場合 についてはノーチェックです。sprintf()を使った方法については、 本の中でもその続きで説明しています。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
83 | Re^3: 質問4:うまくいかないint_to_strについて | コメント数: 1件 |
D.Matsu | dmatsu@gld.mmtr.or.jp | 2001/07/18 (水) 12:34 | |
本書の方は読んでいないのですが、 > という出力が得られました。ptr1とptr2が同じbufを指しているので誤動作が起きる > というのが元課題の趣旨ですね。 という事であれば > char str1[20]; > char str2[20]; > > char *ptr1 = str1; > char *ptr2 = str2; この部分は冗長ですね。 #あとの処理でptr1,2にはbufのポインタが入るのでstr1,2とも使用されません。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
82 | Re: ”C言語 体当たり学習(徹底入門)”のmy_splitについて | コメント数: 1件 |
かずま | sakamoto@mc.catv.ne.jp | 2001/07/18 (水) 11:30 | |
list3-7 では、#define OUT_FILE_SIZE 1400000 なので、 2MB のファイルは、2個のファイルに分割されます。 ところが、ダウンロードしたースでは、 #define OUT_FILE_SIZE 140000 となっているため、 2MBのファイルを分割した場合、15個のファイルを作ろうとします。 このプログラムは、ファイル名の生成方法に問題があり、 最初の 10個のファイルは、split0, split1, ..., split9 という名前に なりますが、11個目からは split:, split;, split<, split=, ... と なります。これらは、Windows では許されないファイル名です。 修正方法は、 13: char out_file_name[] = "split000"; 41: sprintf(out_file_name, "split%03d", out_file_count); |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
81 | Re^11: 質問6:スタックオーバーフローの実験 | コメント数: 0件 |
(ぱ) | maebashi@cse.co.jp | 2001/07/13 (金) 22:59 | |
http://member.nifty.ne.jp/maebashi/ | ||
> > # とはいうものの、この問題に関しては、やっぱり読んだ人に自力 > > # で考えてもらいたい気がします。必要な情報はそれより前に全て > > # 書いてあるつもりですので。 > > 出過ぎたマネをして本当に申し訳ありませんm(_ _)m いえその、そんな恐縮されてしまうと恐縮してしまいますが f(^^;;; |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
80 | Re: 質問6:スタックオーバーフローの実験 | コメント数: 0件 |
REC | tabe@mug.biglobe.ne.jp | 2001/07/13 (金) 00:28 | |
http://ncosweb.h2o-lp.co.jp | ||
> // stackoverflow.c ... スタックオーバーフローのテスト よくある、スタックオーバーフローは、 2次元配列で発生すると、経験しているのですが、 grep "][" *.c あれ、こうかな? grep "\]\[" *.c 窓の人達、ごめんなさい。UNIXしか知らないもので。 ※「現在のフォルダのすべてのCソースの中で、2次元配列を検出する」の意味 で、えー、皆さん どんな時、スタックオーバーフローしますか? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
79 | Re^10: 質問6:スタックオーバーフローの実験 | コメント数: 1件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/12 (木) 23:23 | |
> # とはいうものの、この問題に関しては、やっぱり読んだ人に自力 > # で考えてもらいたい気がします。必要な情報はそれより前に全て > # 書いてあるつもりですので。 出過ぎたマネをして本当に申し訳ありませんm(_ _)m 「完全制覇」のFig 2-5, 2-6, 2-7に詳しく図解してありますね。 # これらの図の方が私なんかの文章の何倍も説得力あるし...(^^;) # なんでこれらの図で理解できなくて私の説明で理解できたのかしら? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
78 | Re: 質問5:va_endの引数 | コメント数: 0件 |
(ぱ) | maebashi@cse.co.jp | 2001/07/12 (木) 20:15 | |
http://member.nifty.ne.jp/maebashi/ | ||
対応が遅くなりましてすみません。 > 「C言語ポインタ徹底制覇」p104va_endの引数について > va_end();と書かれていますが、gccでは引数がないとコンパイル > エラーになりました。stdarg.hを見てみますと、va_arg(ap)でないと > まずいようですが誤植でしょうか。 こちらのミスです。申し訳ありません。 帰宅しましたら正誤表に載せておきます。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
77 | Re^9: 質問6:スタックオーバーフローの実験 | コメント数: 2件 |
(ぱ) | maebashi@cse.co.jp | 2001/07/12 (木) 20:13 | |
http://member.nifty.ne.jp/maebashi/ | ||
本多さん、いろいろとありがとうございます。 # とはいうものの、この問題に関しては、やっぱり読んだ人に自力 # で考えてもらいたい気がします。必要な情報はそれより前に全て # 書いてあるつもりですので。 >> 要は、auto変数の領域の次の次から始まるエリアの中身が関数 >>ポインタだとわかれば順々に処理していくと。 いえ、「エリアの中身が関数ポインタだとわか」るわけもありませ んし、わかったところでわざわざそんなことをする必然性もないで すよね。 どんな方法でhello()に突入したにせよ、hello()の末尾では、 returnするための機械語命令が実行されます。 そして、そのときスタックはやっぱりhello()へのポインタで埋まっ ていますから、またhello()に「戻ろうとする」わけです(だから、 格納したhello()へのポインタの数の数分の1しかhello()は呼ばれ ないはず)。 # その昔、「GOSUB XXX: RETURN」を「GOTO XXX」に書き直したり # しませんでした? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
76 | Re^8: 質問6:スタックオーバーフローの実験 | コメント数: 3件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/11 (水) 21:12 | |
> ということでbufの最後の要素の、次の、次にmainへの戻りが入っているようです。 > そこからずーっと強制的に関数ポインタを入れると、処理系としては順々に処理するのでしょうか。 > 要は、auto変数の領域の次の次から始まるエリアの中身が関数ポインタだとわかれば順々に処理していくと。 ここはOSの環境に依存する話だし、FreeBSDを知らないのでわかりませんが、 たぶんそうなのでしょう。 せっかくだから、続けて以下を調べてみては? - func()が引数をとるようにしたら引数はbuf[]の上にあるのか下にあるの? - buf[]以外の変数を用意したらそれらはどういう順番で積み上げられるんだろう? - func()が返却値を返すとしたらそれを返すための領域は確保されるのかな? - buf[-1],buf[-2]にはどんな値が入っているのでしょうね。 意味のある数字が入っているのかしら? - func()が可変長引数の関数だったら戻り位置の格納位置はどこにあるのかしら? 呼び出し方がfunc(1,buf[0])とfunc(2,buf[0],buf[1])で違いがあるのかしら? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
75 | Re^7: 質問6:スタックオーバーフローの実験 | コメント数: 0件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/11 (水) 21:03 | |
> buf[12]... place:0xefbfdaec content(c):A content(p):0x44434241 > ということでわたしには内容に法則性は見出せませんでした。mainのbufも入っていないようです。 > (ABC..というところがなかった) # 私のマシンとエンディアンが違うのね... 0x41='A', 0x42='B', 0x43='C', 0x44='D'ですね。 void *のサイズは4 Bytes(環境依存)なのに対してcharは1 Byteです。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
74 | Re^7: 質問6:スタックオーバーフローの実験 | コメント数: 4件 |
ラソーダ監督 | 2001/07/11 (水) 19:55 | |
ということで、buf[10]近傍にmainへの戻り情報が入っているのだと仮定して void func(void) { void *buf[10]; void *maybe_main; static int i; maybe_main = buf[???]; // ここをいろいろ変えてみる for (i = 0; i < 13; i++) { buf[i] = maybe_main; } } int main () { char buf[10]; strcpy(buf, "ABCDEFGHIJ"); func(); fprintf(stderr, "ここを通った\n"); return 0; } として???の値をいろいろ変えてみると、maybe_mainがbuf[11]のときに「ここを通った」と表示され正常終了しました。 ということでbufの最後の要素の、次の、次にmainへの戻りが入っているようです。 そこからずーっと強制的に関数ポインタを入れると、処理系としては順々に処理するのでしょうか。 要は、auto変数の領域の次の次から始まるエリアの中身が関数ポインタだとわかれば順々に処理していくと。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
73 | Re^6: 質問6:スタックオーバーフローの実験 | コメント数: 6件 |
ラソーダ監督 | 2001/07/11 (水) 19:55 | |
buf[0]... place:0xefbfdabc content(c):^\ content(p):0xefbfdb1c buf[1]... place:0xefbfdac0 content(c):リ content(p):0xefbfdad8 ... buf[9]... place:0xefbfdae0 content(c):- content(p):0x172d buf[10]... place:0xefbfdae4 content(c):\222^Oj content(p):0xefbfdaf8 buf[11]... place:0xefbfdae8 content(c):5 content(p):0x1735 buf[12]... place:0xefbfdaec content(c):A content(p):0x44434241 ... buf[19]... place:0xefbfdb08 content(c):( content(p):0xefbfdb28 buf[20]... place:0xefbfdb0c content(c):^@ content(p):0x0 ということでわたしには内容に法則性は見出せませんでした。mainのbufも入っていないようです。 (ABC..というところがなかった) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
72 | Re^5: 質問6:スタックオーバーフローの実験 | コメント数: 7件 |
ラソーダ監督 | 2001/07/11 (水) 19:54 | |
本多さん、本当にありがとうございます。 まず、 void func(void) { void *buf[10]; static int i; for (i = 0; i < 20; i++) { // 見るだけなら暴走しない? printf("buf[%d]... place:%p\tcontent(c):%c\t\tcontent(p):%p\n", i, &buf[i], buf[i], buf[i]); } for (i = 0; i < 13; i++) { // これだと「hello!」と2回言ってコアダンプ buf[i] = hello; } } int main () { char buf[10]; strcpy(buf, "ABCDEFGHIJ"); func(); return 0; } として見ましたが、 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
71 | Re^4: 質問6:スタックオーバーフローの実験 | コメント数: 8件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/11 (水) 18:11 | |
> これは、buf[11]以降が戻り情報のスタック(コールスタックと言うんですか?)に > なっていて、関数ポインタが尽きるまで実行される、という認識でいいんですか? このあたりは環境に依存する話なのでbuf[11]以降がすべて戻り位置情報か どうかはわからないのですが (私の環境ではbuf[1000]くらいまでhello()へのポインタで埋めても hello()は呼び出されませんし) Free BSDではきっとそうなのでしょう。 helloを代入する前にbuf[11]〜buf[20]にどんな値が入っているのか 確認してみてください。 また、main()のbuf[0]〜buf[9]に何か値を格納してfunc()中の buf[11]〜buf[30]あたりを表示すると、main()のbuf[0]〜buf[9]に 入れた値が読み出せるはず。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
70 | Re^3: 質問6:スタックオーバーフローの実験 | コメント数: 9件 |
ラソーダ監督 | 2001/07/11 (水) 16:24 | |
> 今回で言うとbuf[19]あたりの位置に戻り位置情報があったんだと思います。 > 戻り位置情報がhello関数ポインタで書き換えられてしまったため、 > main()の呼び出し位置ではなくhello()へ戻って(?)しまったのです。 うおおおお、そうか!!!分かりました。大変ありがとうございます。3日間の 悩みが晴れました。このループのところは、 for (i = 0; i < 12; i++) { だと「hello!」と1回言ってコアダンプし、 for (i = 0; i < 13; i++) { だと「hello!」と2回言ってコアダンプします。 これは、buf[11]以降が戻り情報のスタック(コールスタックと言うんですか?)に なっていて、関数ポインタが尽きるまで実行される、という認識でいいんですか? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
69 | Re^2: 質問6:スタックオーバーフローの実験 | コメント数: 10件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/11 (水) 07:07 | |
> 分からないのが、buf[i] = hello;は関数ポインタを代入しているだけなのに、 > 領域を壊したら中身が実行されたことです。 buf[10]のような自動変数は通常スタックと呼ばれるメモリの領域に確保されます。 関数が呼び出されたときスタックと言う領域にbuf[10]のための領域を確保します。 そのとき関数の呼び出し元に戻るためのポインタ情報も(ユーザには内緒で) スタックに書き込まれます。 普通、スタックはアドレスの大きいところから小さい方に向けて変数などの領域を 割り当てていきます。 だから戻り位置情報はbufより大きなアドレスの位置に書かれています。 今回で言うとbuf[19]あたりの位置に戻り位置情報があったんだと思います。 戻り位置情報がhello関数ポインタで書き換えられてしまったため、 main()の呼び出し位置ではなくhello()へ戻って(?)しまったのです。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
68 | Re: 質問6:スタックオーバーフローの実験 | コメント数: 11件 |
ラソーダ監督 | 2001/07/10 (火) 17:19 | |
まずbuf[18]という配列範囲外のエリアとhelloのポインタ値を表示したのですが mem place of buf[18]:0xefbfdb0c mem place of hello:0x15f8 と遠く離れた値が出ました。(最初関数ポインタの位置を壊したのかと思ったのですが はずれました)次にiの値を色々変えて実行したのですが、上の注釈のようにありました 。分からないのが、buf[i] = hello;は関数ポインタを代入しているだけなのに、領域を 壊したら中身が実行されたことです。あと、本にはmainの方にbuf[10]という領域があり ますが、これは実験に必要なのでしょうか?質問ばかりで申し訳ありませんが、よろし かったらご教示をお願いします。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
67 | 質問6:スタックオーバーフローの実験 | コメント数: 13件 |
ラソーダ監督 | 2001/07/10 (火) 17:19 | |
「C言語ポインタ完全制覇」p100stackoverflow.cについて (ここまでの質問で、書名を間違えておりました。大変申し訳ありません。) p100stackoverflow.cについて「どうしてこうなるのか考えてみてください」との ことで3日間考え続けたのですが、やはりわかりません。情けないです。 #include <stdio.h> // stackoverflow.c ... スタックオーバーフローのテスト void hello(void) { fprintf(stderr, "hello!\n"); } void func(void) { void *buf[10]; static int i; printf("mem place of buf[18]:%p\n", &buf[18]); printf("mem place of hello:%p\n", &hello); // for (i = 0; i < 10; i++) { // これだと何も起きない(当たり前) // for (i = 0; i < 11; i++) { // これだとコアを吐くだけ for (i = 0; i < 19; i++) { // これだと「hello!」と8回言ってコアダンプ buf[i] = hello; } } int main () { // int buf[10]; // これはあってもなくてもいいらしい func(); return 0; } 上のように改造して実行しました。(続く) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
66 | Re^2: 昨日から「ポインタ完全制覇」を読み始めました。質問1void*の加算 | コメント数: 0件 |
ラソーダ監督 | 2001/07/10 (火) 10:42 | |
> void *を加算するのはANSIではできないことになっているんですが > gccの独自拡張によって可能になってしまっています。 本多様、お返事ありがとうございます。 独自拡張したということは、何かいいことがあるんでしょうね。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
65 | Re^3: 質問4:うまくいかないint_to_strについて | コメント数: 0件 |
ラソーダ監督 | 2001/07/10 (火) 10:39 | |
charポインタとchar配列については、 #include <stdio.h> int str_len(char *str) { int i; for(i = 0; ; i++) { if(str[i] == '\0') return i; } } int main () { char str[10] = "abcde"; int len = str_len(str); printf("str:%s len:%d\n", str, len); return 0; } というプログラムは動きますよね。 配列名strは読み出しの値としてはポインタとして使えるということでしょうか? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
64 | Re^2: 質問4:うまくいかないint_to_strについて | コメント数: 3件 |
ラソーダ監督 | 2001/07/10 (火) 10:39 | |
本多様、お返事ありがとうございました。 int main (void) { char str1[20]; char str2[20]; char *ptr1 = str1; char *ptr2 = str2; ptr1 = int_to_str(5); ptr2 = int_to_str(10); printf("ptr1:%s ptr2:%s\n", ptr1, ptr2); return 0; } とすると、意図どおり意図と違う動きをし(?)、 % int_to_str ptr1:10 ptr2:10 という出力が得られました。ptr1とptr2が同じbufを指しているので誤動作が起きる というのが元課題の趣旨ですね。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
63 | Re: 質問4:うまくいかないint_to_strについて | コメント数: 4件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/10 (火) 06:58 | |
> 「C言語ポインタ徹底制覇」p098うまくいかないint_to_strについて あれ?本の名前が違うような...? > char str1[20]; > char str2[20]; > str1 = int_to_str(5); > str2 = int_to_str(10); > str1、str2はchar型のポインタを受けるのでcharの配列でいいかと思ったのですが > ・・・。 もう一度「完全制覇」を通読されてはいかがですか? charポインタとchar配列は別物ですよ。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
62 | Re: 質問3:文字列リテラルの書き換え | コメント数: 0件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/10 (火) 06:55 | |
> 「C言語ポインタ徹底制覇」p088文字列リテラルの書き換えについて > 空白を読み飛ばした次の文字がEOFの場合EOFを返していますが、単語を読み込めた > funcという関数の中で、char *str="abc";という文を実行したあとで、strを表示し > 、その後でstr[0]='d';という文を実行すると、もし文字列リテラルが書き換え可能 > な処理系だと、funcの1回目は正しくabcと表示するが、2回目はdbcと出すと書か > れています。そのような処理系が手元にないので実験できませんが、これはなぜで > しょうか。"abc"がポインタだということは分かるのですが、2回目もchar *str="a > bc";を通るので、やはり同じ結果になるような気がするのですが・・・。 strが'a' 'b' 'c'という文字が格納されたメモリ上のどこかを指しているのは わかりますよね?そこを直接書き換えているんですよ。 ちなみにstr="abc"という初期化はあくまでポインタの初期化ですから。 strポインタが指す位置が最初に通ったときと同じ物を指すように 初期化されるだけで指している先を"abc"で埋めるように 初期化するわけじゃないんですよね。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
61 | Re: 昨日から「ポインタ完全制覇」を読み始めました。質問1void*の加算 | コメント数: 1件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/10 (火) 06:49 | |
> ポインタにn加算すると指す型のサイズのn倍進む、という話ですが、ではvoid* > を加算したらどうなるだろう・・・と興味を持ちやってみると、1ずつ進みました。 > エラーになるかゼロ進むのが正しいと思うのですが、コンパイラの間違いでしょ > うか? void *を加算するのはANSIではできないことになっているんですが gccの独自拡張によって可能になってしまっています。 gccって独自拡張をたくさんやっているのでgccでOK→ANSI合致なんて 思っちゃいけないようです。 gccでは//っていうコメント記号や関数内関数が記述できちゃうんですもの。 便利だからいいけど。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
60 | Re^17: 可変長構造体は規格違反ではない! | コメント数: 0件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/10 (火) 06:45 | |
> > もっともせっかくC++を使っていて、こいつらを使わないことが、 > > どれだけあるのかわかりませんが...(^^;) > というか、可変長構造体の話ですから、C言語のソースを > そのままC++でコンパイルした時に、C++の規格にてらして > どうなるかの話であり、すなわちC言語と互換性のある機能 > しか使わない時の話です。 元ねたはそういう話でしたね。重ね重ねご指摘ありがとうございます。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
59 | 質問5:va_endの引数 | コメント数: 1件 |
ラソーダ監督 | 2001/07/10 (火) 01:14 | |
「C言語ポインタ徹底制覇」p104va_endの引数について va_end();と書かれていますが、gccでは引数がないとコンパイルエラーになりまし た。stdarg.hを見てみますと、va_arg(ap)でないとまずいようですが誤植でしょう か。もしそうでなかったら平にお許しください。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
58 | 質問4:うまくいかないint_to_strについて | コメント数: 5件 |
ラソーダ監督 | 2001/07/10 (火) 01:10 | |
「C言語ポインタ徹底制覇」p098うまくいかないint_to_strについて int_to_strという関数がうまく動かない例を実際に体験してみようと思いまして、 次のようなプログラムを作りました。 #include <stdio.h> #include <stdlib.h> char *int_to_str(int i) { // int を文字列に変換 static char buf[20]; sprintf(buf, "%d", i); return buf; } int main (void) { char str1[20]; char str2[20]; str1 = int_to_str(5); str2 = int_to_str(10); printf("str1:%s str2:%s\n", str1, str2); return 0; } ところが、うまくいかない以前にコンパイルエラーになります。 gcc int_to_str.c -o int_to_str int_to_str.c: In function `main': int_to_str.c:14: incompatible types in assignment int_to_str.c:15: incompatible types in assignment str1、str2はchar型のポインタを受けるのでcharの配列でいいかと思ったのですが ・・・。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
57 | 質問3:文字列リテラルの書き換え | コメント数: 1件 |
ラソーダ監督 | 2001/07/10 (火) 01:04 | |
「C言語ポインタ徹底制覇」p088文字列リテラルの書き換えについて 空白を読み飛ばした次の文字がEOFの場合EOFを返していますが、単語を読み込めた funcという関数の中で、char *str="abc";という文を実行したあとで、strを表示し 、その後でstr[0]='d';という文を実行すると、もし文字列リテラルが書き換え可能 な処理系だと、funcの1回目は正しくabcと表示するが、2回目はdbcと出すと書か れています。そのような処理系が手元にないので実験できませんが、これはなぜで しょうか。"abc"がポインタだということは分かるのですが、2回目もchar *str="a bc";を通るので、やはり同じ結果になるような気がするのですが・・・。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
56 | 質問2:単語を読み込む関数の戻り値 | コメント数: 0件 |
ラソーダ監督 | 2001/07/10 (火) 00:59 | |
「C言語ポインタ徹底制覇」p067get_word.cについて 空白を読み飛ばした次の文字がEOFの場合EOFを返していますが、単語を読み込めた 時は単語の長さを返しています。この場合、EOFの場合はゼロを返した方が正しい のではないでしょうか・・・?呼び出し側の判定でもEOFかどうかで判定し、gccのstd io.hでは(-1)なので問題ないかもしれませんが、もし正の数の処理系があったら困 るのでは・・・?(初学者だからかもしれませんが、EOFとかプリプロセッサマクロが 入っていると移植性が気になります) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
55 | 昨日から「ポインタ完全制覇」を読み始めました。質問1void*の加算 | コメント数: 2件 |
ラソーダ監督 | 2001/07/10 (火) 00:58 | |
はじめまして。昨日から「ポインタ完全制覇」を読み始めました。初学者です のでつたない質問になろうかと思いますが、前橋先生、皆さん、もしお時間が ありましたらご教示ください。また、質問の仕方に問題がありましたら合わせ てご教示ください。購入したのは第4刷、環境はFreeBSDとgccです。 p044ポインタ演算について ポインタにn加算すると指す型のサイズのn倍進む、という話ですが、ではvoid* を加算したらどうなるだろう・・・と興味を持ちやってみると、1ずつ進みました。 エラーになるかゼロ進むのが正しいと思うのですが、コンパイラの間違いでしょ うか? |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
54 | Re^16: 可変長構造体は規格違反ではない! | コメント数: 1件 |
のぐー | BXM06466@nifty.ne.jp | 2001/07/09 (月) 23:33 | |
http://homepage1.nifty.com/nogue/ | ||
> もっともせっかくC++を使っていて、こいつらを使わないことが、 > どれだけあるのかわかりませんが...(^^;) というか、可変長構造体の話ですから、C言語のソースを そのままC++でコンパイルした時に、C++の規格にてらして どうなるかの話であり、すなわちC言語と互換性のある機能 しか使わない時の話です。 コンストラクタやデストラクタのあるクラスは、そもそも mallocしてはいけませんし、たとえコンストラクタ等が 無くても、クラス(構造体)を継承した場合もメンバ順は 未規定になるような記述があります。念のため。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
53 | Re^15: 可変長構造体は規格違反ではない! | コメント数: 2件 |
本多 | manybook@msc.biglobe.ne.jp | 2001/07/09 (月) 11:24 | |
> >その保証がなくなってるのはC++じゃなかったかしら。 > ということらしいので、access-specifierを書かなければ、 > C++でも大丈夫のようです。 えっ、そうなんですか?知らなかった。ご指摘どうもありがとうございます。 access-specifierってpublicとかprivateとかprotectedとか(他にあったかしら?) ですよね。 もっともせっかくC++を使っていて、こいつらを使わないことが、 どれだけあるのかわかりませんが...(^^;) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
52 | Re^14: 可変長構造体は規格違反ではない! | コメント数: 3件 |
のぐー | BXM06466@nifty.ne.jp | 2001/07/09 (月) 05:43 | |
http://homepage1.nifty.com/nogue/ | ||
>その保証がなくなってるのはC++じゃなかったかしら。 ISO/IEC 14882:1998 9.2 Class members 12 Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of nonstatic data members separated by an access-specifier is unspecified (11.1) . Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1). ということらしいので、access-specifierを書かなければ、 C++でも大丈夫のようです。 |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
51 | Re: ヘッダ解析ツール? | コメント数: 0件 |
REC | tabe@mug.biglobe.ne.jp | 2001/07/06 (金) 21:38 | |
http://ncosweb.h2o-lp.co.jp | ||
gccだと-M で使っているヘッダがわかり、 Soralis のLINT −Nlevel=4だと、 このヘッダいらん等と言ってくれます。 窓の方はしりません。 > あるソースを見ると、結構たくさんのヘッダファイルをインクルードしていたりします。 > 本当にこんなにたくさんのヘッダファイルをインクルードする必要があるかと思い、 > わざわざ、インクルードしている部分をコメントアウトして、コンパイルして確かめたり > しています。 > > このような面倒な事しなくても、そのファイルが本当に必要としているヘッダファイルが一発でわかるような、 > ツールどなたか知りませんでしょうか?(Windows版で) |
【新規投稿】 【この投稿にリプライ】 【投稿者削除】 |
Copyright(C) 1999 NIFTY Corporation All Rights Reserved. |