K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[562] Re:大したことではないのですが
投稿者:(ぱ)
2007/02/20 02:13:25

>http://kmaebashi.com/programmer/devlang/yacclex.html 上のyaccfile.png >という画像の説明において、mycalc.l → yacc となっているのが気になりました >(mycalc.y → yacc ですよね?間違っていたらゴメンナサイ)。 ご指摘ありがとうございます。 おっしゃるとおり間違っていますので、修正しました。ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[561] aaaaa
投稿者:yosyyi
2007/02/20 02:13:25

aaaaaa
[この投稿を含むスレッドを表示] [この投稿を削除]
[560] aaaaa
投稿者:yosyyi
2007/02/20 02:13:25

aaaaaa
[この投稿を含むスレッドを表示] [この投稿を削除]
[559] 大したことではないのですが
投稿者:hajimemasite
2007/02/20 02:13:25

はじめまして。 yacc/lex の解説ページを探していてたどり着きました。 説明がわかりやすくて助かります。 http://kmaebashi.com/programmer/devlang/yacclex.html 上のyaccfile.png という画像の説明において、mycalc.l → yacc となっているのが気になりました (mycalc.y → yacc ですよね?間違っていたらゴメンナサイ)。 これからも頑張ってください。
[この投稿を含むスレッドを表示] [この投稿を削除]
[558] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>大変失礼しました。私の能力の低さが露呈してます(T-T) ぐぁっ、私はそこって全然気がつきませんでした(T_T)
[この投稿を含むスレッドを表示] [この投稿を削除]
[557] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>とはいえいわゆる non-ANSI な超古い処理系ではダメなのもあったような記憶がうっすらと。 あ、non-ANSIは知らないです。いわゆる「ぬるぽ」になるかもしれませんね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[556] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 >C89もセーフですよ。 とはいえいわゆる non-ANSI な超古い処理系ではダメなのもあったような記憶がうっすらと。 そーいう化石のようなプラットフォームまで考えるかどうか次第かな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[555] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

>>>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 >>C89もセーフですよ。 確かにfree(NULL)は無問題なのですが、以下の※の箇所は大問題でした。 | if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { | fprintf(stderr,"ERROR: memory allocation\n"); | goto LERROR; ←ココ | } (中略) | LERROR: | free( prm->cpItem); ← ※ | free( prm); | return NULL; |} このような箇所は「if ( prm ) free( prm->cpItem);」が必要ですね。 以下の箇所も間違っていますね。 誤>void PrmDestroy( typChangePrm *prm) 誤>{ 誤> int i; 誤> 誤> for ( i=0; i<prm->itemCount; i++) 誤> free(prm->cpItem); 誤> free(prm->cpItem); 誤> free(prm); 誤>} 正>void PrmDestroy( typChangePrm *prm) 正>{ 正> int i; 正> 正> if ( prm && prm->cpItem) { 正> for ( i=0; i<prm->itemCount; i++) { 正> free(prm->cpItem[i]); 正> } 正> } 正> if ( prm) free(prm->cpItem); 正> free(prm); 正>} 大変失礼しました。私の能力の低さが露呈してます(T-T)
[この投稿を含むスレッドを表示] [この投稿を削除]
[554] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>realloc() に失敗する状況でどうリカバリーするかの仕様次第ですけど、 >書かない癖つけたほうがいいと思う。 私もそう思います。 なので私のサンプルはメモリの再配置が多そうだったことも含めて 完全にfree()してしまったりしてます(^-^;)
[この投稿を含むスレッドを表示] [この投稿を削除]
[553] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 C89もセーフですよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[552] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>矢印の箇所でgotoしたとき、prmはNULLだからSegmentation faultになりませんか。 C89 でどうだったかは知りませんが少なくとも C99 では free() の解説に、空ポインタの場合何もしないとあるので無問題です。 MSDN や HPUX11.00 の man にも同一の旨の記述があります。
[この投稿を含むスレッドを表示] [この投稿を削除]
[551] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

>typChangePrm *CreatePrm( char *cString, int itemCount) >{ > typChangePrm *prm = NULL; > int i; > > if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { > fprintf(stderr,"ERROR: memory allocation\n"); > goto LERROR; ←ココ > } (中略) > LERROR: > free( prm->cpItem); > free( prm); > return NULL; >} 矢印の箇所でgotoしたとき、prmはNULLだからSegmentation faultになりませんか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[550] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

こんな感じかなぁ? 要素追加しちゃったけど。 ---- #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct{ int itemCount; char cString[50]; char **cpItem; } typChangePrm; typChangePrm *CreatePrm( char *cString, int itemCount) { typChangePrm *prm = NULL; int i; if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } if ( strlen( cString) >= 50 ) return NULL; strcpy( prm->cString, cString); prm->itemCount = itemCount; if ( (prm->cpItem = malloc( sizeof(char *) * itemCount )) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } for ( i=0; i<itemCount; i++) prm->cpItem[i] = NULL; return prm; LERROR: free( prm->cpItem); free( prm); return NULL; } void PrmDestroy( typChangePrm *prm) { int i; for ( i=0; i<prm->itemCount; i++) free(prm->cpItem); free(prm->cpItem); free(prm); } void PrmResize( typChangePrm *prm, int itemCount) { char **tmp; int i; if ( prm->itemCount >= itemCount ) { for ( i=itemCount; prm->i<itemCount; i++) free( prm->cpItem[i]); prm->itemCount = itemCount; return; } tmp = prm->cpItem; if ( (tmp = realloc( tmp, sizeof(char *) * itemCount)) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } prm->cpItem = tmp; for ( i=prm->itemCount; i<itemCount; i++) prm->cpItem[i] = NULL; prm->itemCount = itemCount; return; LERROR: free( prm->cpItem); } void PrmSetItem( typChangePrm *prm, int item_no, char *item) { if ( item_no >= prm->itemCount) return; if ( (prm->cpItem[ item_no] = strdup( item)) == NULL) fprintf(stderr,"ERROR:memory allocation\n"); } void PrmShow( typChangePrm *prm) { int i; printf("********************************\n"); printf("Item Count:%d\n",prm->itemCount); printf("cString :%s\n",prm->cString); for ( i=0; i<prm->itemCount; i++) printf("Item[%d]:%s\n",i,((prm->cpItem[i]==NULL)?"NULL":prm->cpItem[i])); } int main(void) { typChangePrm *prm; char *item[] = { "hello", "world", "program"}; if ( (prm = CreatePrm("c-string",2)) == NULL) return 1; PrmSetItem(prm,0,item[0]); PrmSetItem(prm,1,item[1]); PrmShow( prm); PrmResize( prm, 3); PrmSetItem(prm,2,item[2]); PrmShow( prm); PrmResize( prm, 1); PrmShow( prm); PrmDestroy(prm); return 0; }
[この投稿を含むスレッドを表示] [この投稿を削除]
[548] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>data.cpItem[n] = realloc( data.cpItem[n], new_size); 皆さん同じコードをかかれていますけど、これってダメコードですよ。 realloc() に失敗したら、旧 data.cpItem[n] がリークしますね。 # 旧値が失われて復旧の手段が無い。 realloc() に失敗する状況でどうリカバリーするかの仕様次第ですけど、 書かない癖つけたほうがいいと思う。
[この投稿を含むスレッドを表示] [この投稿を削除]
[547] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

>要はコダマンさんが、 > ・cpItem自体をreallocしたいのか > ・cpItem[n]のほうをreallocしたいのか >に尽きるんじゃないでしょうか。 要求をちゃんと定義してもらわずに作業を始めると戻り工数が大きくなりますよねー 私は最初「構造体の中のポインタ配列のreallocの方法」と言ってるので typedef struct{ char cString[50]; char *cpItem[]; }typChangePrm; typChangePrm data; data.cpItem[n] = realloc( data.cpItem[n], new_size); の程度のことを質問してると思ってましたが...(^^) 日本語の解釈って色々できるんですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[546] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

要はコダマンさんが、  ・cpItem自体をreallocしたいのか  ・cpItem[n]のほうをreallocしたいのか に尽きるんじゃないでしょうか。 まきじさんのサンプルは前者をrealloc()ですけれど、 後者も行いたい場合はやはりこちらもrealloc()で書いたほうが便利でしょうね。 # あとcpItem自体が縮小した場合の考慮をしないとメモリリークしますね。 # ってここはツッコミ入れなくても大丈夫か(^-^;)
[この投稿を含むスレッドを表示] [この投稿を削除]
[545] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

>…が、既にかずまさんからツッコミが入ってますが、まきじさんのコードだと、 >2回目のrealloc()でも第一引数にNULL渡してますね…ケアレスミスだとは思いますが。 よく読んでなかったのでここも修正です… 2回目のrealloc()は別に領域拡張しているわけではなく、単なるmalloc()と 同値なので、上の私の記述は見当外れですね。失礼しました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[544] Re:reallocについて
投稿者:まきじ
2007/02/20 02:13:25

>最初から第一引数に定数のNULLを渡すくらいなら、malloc()を使うべきでしょう。 realloc() の質問でしたので、realloc() にしただけです。 特に深い意味、意図はないです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[543] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

>>>data.cpItem[i] = malloc(sizeof(char) * 64); > >realloc() の第一引数を、NULL にすれば、malloc() と同じ動作をします。 >よって、realloc(NULL,sizeof(char) * 64); でも問題ありません。 いや、もちろんそれは知っていますが、スタイルとしてどちらを取るかという 問題です。 もともと、realloc()の第一引数をNULLにすればmalloc()と同じ動作をする、 という仕様は、最初のメモリ確保と2回目以降のメモリ確保とで別々のコードを 記述する手間を避けるためのものでしょう。 ですから、この例で言えば、data.cpItemの指す先を確保した際、 その中身を全部NULLに初期化しておけば、 data.cpItem[i] = realloc(data.cpItem[i],sizeof(char) * 64); と書けば、このポインタの指す先にデータが来るかどうかわからないような 時、重複したコードを書かなくてよくなるわけです。 この仕様自体はそれなりに便利なものだとは思うのですが(でもこれも realloc()の仕様としてはオーバースペックだという意見もありうるわけですが)、 最初から第一引数に定数のNULLを渡すくらいなら、malloc()を使うべきでしょう。 …が、既にかずまさんからツッコミが入ってますが、まきじさんのコードだと、 2回目のrealloc()でも第一引数にNULL渡してますね…ケアレスミスだとは思いますが。 これは私は気付いていませんでした。
[この投稿を含むスレッドを表示] [この投稿を削除]
[542] Re:reallocについて
投稿者:まきじ
2007/02/20 02:13:25

>最初の 10個の領域とは別に、新たに 20個の領域を確保 *(data.cpItem + i) = realloc(NULL,sizeof(char) * 64); で、要素数が 64 個の char 型配列が新たに、20 個確保されていると云うことですね? それより前で、10 個確保されているので、第一引数に NULL を指定すると、 新たに 20 個確保され10 個分、余分にメモリを消費する。 だから、解放するか、20 個の内 10 個は、前と同じ内容なので、残りの 新たに確保された領域 10 個に対して、malloc() してやれば良いですね。 data.cpItem[10] から領域を新たに確保という事で for(i = 10;i < 20; i++){ *(data.cpItem + i) = realloc(NULL,sizeof(char) * 64); strcpy(*(data.cpItem + i),str); } でどうでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[541] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

そういうわけで私流に書き直してみるテスト。 --- #include <stdio.h> #include <stdlib.h> #include <string.h> typedef enum { true = (1 == 1), false = !true } boolean; typedef struct{ char cString[50]; char **cpItem; } typChangePrm; void freeMemory(typChangePrm *data) { int i; printf("freeMemory - start\n"); for(i = 0; data->cpItem[i]; i++) { printf(" free(item) : pointer[%p]\n", data->cpItem[i]); free(data->cpItem[i]); } printf(" free(item container) : pointer[%p]\n", data->cpItem); free(data->cpItem); data->cpItem = NULL; printf("freeMemory - end\n"); return; } boolean allocateMemory(typChangePrm *data, size_t itemSize) { char **prevMemory; size_t allocateSize; int i; printf("allocateMemory - start\n"); if (data->cpItem != NULL) { freeMemory(data); } data->cpItem = calloc(itemSize + 1, sizeof(char *)); // +1して番兵をつける printf(" allocate(item container) : pointer[%p]\n", data->cpItem); for(i = 0;i < itemSize; i++){ data->cpItem[i] = calloc(64, sizeof(char)); if (data->cpItem[i] == NULL) { freeMemory(data); // 初期化に失敗したら壊す return false; } printf(" allocate(item) : pointer[%p]\n", data->cpItem[i]); } printf("allocateMemory - end\n"); return true; } int main(void){ typChangePrm data; char str[]="hoge"; size_t allocateSize; size_t itemSize; int i; data.cpItem = NULL; allocateMemory(&data, 10); allocateMemory(&data, 20); freeMemory(&data); return 0; }
[この投稿を含むスレッドを表示] [この投稿を削除]
[540] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

ついでに言うと、2回目のアロケートを以下のように書き直しても   *(data.cpItem + i) = realloc(*(data.cpItem + i), sizeof(char) * 64); realloc失敗時に*(data.cpItem + i)がNULLになってしまってやはりダメですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[539] Re:reallocについて
投稿者:かずま
2007/02/20 02:13:25

>realloc() の第一引数を、NULL にすれば、malloc() と同じ動作をします。 >よって、realloc(NULL,sizeof(char) * 64); でも問題ありません。 malloc も realloc も関係ありません。そのプログラム自体に問題があります。 最初の 10個の領域とは別に、新たに 20個の領域を確保していて、最初の 10個の領域は二度と使えません。これをメモリーリークといいます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[538] Re:reallocについて
投稿者:まきじ
2007/02/20 02:13:25

>>data.cpItem[i] = malloc(sizeof(char) * 64); realloc() の第一引数を、NULL にすれば、malloc() と同じ動作をします。 よって、realloc(NULL,sizeof(char) * 64); でも問題ありません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[537] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

ええと、これはコダマンさんの質問に対するひとつの解答例、ということで よいでしょうか? ところで私なら、 >*(data.cpItem + i) = realloc(NULL,sizeof(char) * 64); この部分はこう書きます。 >data.cpItem[i] = malloc(sizeof(char) * 64);
[この投稿を含むスレッドを表示] [この投稿を削除]
[536] Re:reallocについて
投稿者:まきじ
2007/02/20 02:13:25

#include<stdio.h> #include<stdlib.h> typedef struct{ char cString[50]; char **cpItem; /* ポインタのポインタにする*/ }typChangePrm; int main(void){ typChangePrm data; char str[]="hoge"; int i; /* 10 個の要素を持つポインタの配列を確保 */ data.cpItem = realloc(NULL,sizeof(char*) * 10); for(i = 0;i < 10; i++){ /* *(data.cpItem + i) に 64 個 の要素を持つ char 型の配列を確保 */ *(data.cpItem + i) = realloc(NULL,sizeof(char) * 64); strcpy(*(data.cpItem + i),str); } for(i = 0;i < 10; i++) printf("%s\n",*(data.cpItem + i)); strcpy(str,"foo"); /* ポインタの配列の要素数を 20 個に変更 */ data.cpItem = realloc(data.cpItem,sizeof(char*) * 20); for(i = 0;i < 20; i++){ /* *(data.cpItem + i) に 64 個 の要素を持つ char 型の配列を確保 */ *(data.cpItem + i) = realloc(NULL,sizeof(char) * 64); strcpy(*(data.cpItem + i),str); } for(i = 0;i < 20; i++) printf("%s\n",*(data.cpItem + i)); return 0; }
[この投稿を含むスレッドを表示] [この投稿を削除]
[535] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

はじめまして。 >typedef struct{ > char cString[50]; > char *cpItem[]; //タイプ/処理名/置換先項目/置換元項目/デフォルト値/ >}typChangePrm; まず質問ですが、コンパイラはなんでしょうか? いわゆるANSI-C (ISO-C89)では上のコードは通りません。 ISO-C99なら通ります。gccにも似たような独自拡張があったような。 >↑のような構造体の中のポインタ配列のreallocの方法がわからず苦戦しております。 で、単にcpItemを可変個確保したいだけなら、このページが参考になるでしょう。 http://seclan.dll.jp/c99d/c99d04.htm#dt19990726 確保するサイズは sizeof(typChangePrm) + sizeof(char*) * num ですね。 ただ、それ以前の問題として、こういう構造体をrealloc()する時は、 「この構造体を指しているポインタはないか」ということを意識する必要があります。 realloc()するとアドレスが変わることがあるため、これを指しているポインタがあると そっちも書き換えてやらなければいけません。 それが難しいのなら、可変長構造体を使うのではなく、この構造体に 可変長配列へのポインタを持たせるべきでしょう。 typedef struct{ char cString[50]; char **cpItem; // この先の領域をrealloc()する。 }typChangePrm; # ところでcpItemの数はどっかで保持してるんでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[534] reallocについて
投稿者:コダマン
2007/02/20 02:13:25

始めまして。 typedef struct{ char cString[50]; char *cpItem[]; //タイプ/処理名/置換先項目/置換元項目/デフォルト値/ }typChangePrm; ↑のような構造体の中のポインタ配列のreallocの方法がわからず苦戦しております。 どなたか、ご存知でしたら教えてください。
[この投稿を含むスレッドを表示] [この投稿を削除]
[533] Re:名前のないクロージャで再帰呼び出し
投稿者:(ぱ)
2007/02/20 02:13:25

ええと、まず目的として、クイックソートなんだから当然再帰を使いたい、 ってのがあって、つまりいかにしてquick_sort_sub()を呼び出すかが 問題なわけですが、 以下の箇所で定義されているふたつのクロージャを、それぞれ c1, c2とすると、 fp_op2(closure(quick_sort_sub) { ←c1 return closure(left, right) { ←c2 c2が、通常のクイックソートの実行部ですが、その中では、 その外周のクロージャであるc1の引数である、quick_sort_sub()が 参照できるわけですね。 c1は、引数としてクロージャを受け取り、戻り値としてc2を返すわけですが、 c1の引数にc2を渡して実行できれば万事解決である、と。 で、これを実現しているのがfp_op2()であるわけですが、 これは以下のように書き換えることが可能で、 function fp_op2(f) { c3 = closure(p) { return p(p); }; c4 = closure(x) { c5 = closure(g, h) { return f(x(x))(g, h); }; return c5; }; return c3(c4); } 最後のreturnでc3が実行されていますが、 c3というのは、クロージャを受け取り、そのクロージャにそれ自身を 渡して実行して返す関数なわけで、で、c3のpに実際に渡されているのは c4なので、つまりこのタイミングでc4が実行される。 c4は引数としてxを受け取りますが、c3の定義からして、 xにはc4自身が格納されている。 そして、c4は、戻り値としてc5を返す。 この戻り値は、c3の戻り値でありすなわちfp_op2()の戻り値でもある。 呼び出し元のquick_sort()関数のほうでは、fp_op2()の戻り値に 引数ふたつ与えて評価して、それがクイックソートの実行となる。 で、そのc5ですが、「f(x(x))」のfはつまりc1であり、 その引数の「x(x)」におけるxはc4なので、fの引数には c4の戻り値が渡されることになる。 c4の戻り値であるc5はつまり、引数をふたつとってc1の戻り値 すなわちc2を実行して返す、という、c2のラッパーなので、 当初の目的である 「c1の引数にc2を渡して実行できれば万事解決である」 というのが実現できている… うーん、ぶすぶす… (頭から煙が出ている音) Paul Grahamの「簡潔さは力なり」の中で、 http://www.shiro.dreamhost.com/scheme/trans/power-j.html 数式を散文で書くと量が増える、なんてことが書いてありますが、 数式の力を持ち合わせていない私が書くとこうなってしまうわけで、 やっぱり勉強不足ですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[532] Re:名前のないクロージャで再帰呼び出し
投稿者:NykR
2007/02/20 02:13:25

> …頭から煙が出そうになったので、サンプルのソースを読もうとしてみました。 サンプルをそのまま追うと多分死にます。 簡略化してから追うと fp_op2(closure(f) { return closure(x, y) { ... f(a, b) ... }; }) ⇒ Z Z(c, d) ⇒ closure(f) { return closure(x, y) { ... f(a, b) ... }; }(Z)(c, d) ⇒ closure(x, y) { ... Z(a, b) ... }(c, d) こんな感じです。 参考ページ http://lecture.ecc.u-tokyo.ac.jp/~kawai/pub/is/isis2-note.html http://www.ice.nuie.nagoya-u.ac.jp/~h003149b/lang/fix.html # 「不動点演算子」じゃなかなか見付からないですね。orz # どうやって見付けたんだろう。 == 私も(crowbarを基に)プログラミング言語を作ろうと思っていますが、 そのときは名前付きのクロージャは入れないで、 Schemeの拡張シンタックスのような機能を付けようと思っています。 んで、 named_closure tag (x, y, ...) { ... } と書けば closure(tag) { tag = closure(x, y, ...) { ... }; return tag; }(null) と展開されるようなものをプログラマが自分で作れるようにしたいな、と(不動点演算子はどこへ行った) # で、ライブラリに入れておく
[この投稿を含むスレッドを表示] [この投稿を削除]