1 名前:デフォルトの名無しさん [2007/10/24(水) 04:07:56 ] なんと!意外にもスレが無かったので立ててみました 先日のソフトウェア開発技術者試験午後UのB木のポインタ表現 近年の基本情報技術者試験の午後C言語問題の自己参照構造体 など物凄く出来が悪いです。 ゆとり?文系?自作減少? ブラックボックス化されてメモリ管理やコンピュータの細かい知識が不要となった? 本当にポインターは必要なのか!?議論しましょう
610 名前:デフォルトの名無しさん mailto:sage [2007/12/14(金) 20:17:14 ] >>609 配列の不完全型ってヤツか? 良く分からんが、違う構造体同士で相互参照する時なんかに使う 構造体の不完全型の親戚みたいなもんかな
611 名前:デフォルトの名無しさん [2007/12/15(土) 02:27:42 ] >>609 試せば良いじゃんよ
612 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 02:32:55 ] VC++ExpressEdition d:\work\vc\array\arrayptr.cpp(9) : error C2440: '=' : 'int (*__w64 )[10]' から 'int (*)[]' に変換できません。 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
613 名前:デフォルトの名無しさん [2007/12/15(土) 04:19:56 ] Cより先にアセンブラやれ!! アドレスの概念を理解しないでいきなりやるから 難しくなるんだよ!!
614 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 05:35:26 ] それも極端な話だなあ、と思う反面確かにそれが近道だよなあと思っているおれがいる
615 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 08:55:36 ] ちょっと疑問なんだが、配列自体が先頭のアドレスを示しているのに、 さらにそれのアドレスが欲しい場合ってどういうケース?想像つかないんだけど。
616 名前:デフォルトの名無しさん [2007/12/15(土) 10:40:49 ] こんな感じなら理解できるか? #include <stdio.h> #define N 5 void aryfunc(int ary[N][N]) { int *temp; for(temp = &ary[0][0]; temp != &ary[N-1][N]; temp++){ (*temp)++; } } int main() { int ary[N][N] = {{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}, {16,17,18,19,20},{21,22,23,24,25}}; int *temp,i; for(temp = &ary[0][0],i = 1; temp != &ary[N-1][N]; temp++,i++){ printf("%d ",*temp); if(!(i%5)) putchar('\n'); } aryfunc(ary); for(temp = &ary[0][0],i = 1; temp != &ary[N-1][N]; temp++,i++){ printf("%d ",*temp); if(!(i%5)) putchar('\n'); } return 0; }
617 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 12:08:10 ] >>616 添字でアクセスできるのに、わざわざポインタつかってわかりにくくしてる気がするんだが。 ↓と同じことでしょ? void aryfunc(int ary[N][N]) { int i, j; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { ary[i][j]++; } } }
618 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 12:11:15 ] >>615 配列の配列とか、配列の配列の配列とか、つまり多次元配列を 関数の引数として渡すときに必要だな
619 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 12:15:46 ] >>615 配列名は、配列の「先頭の要素」のアドレス。 配列名に&をつけた場合は配列「そのものの」のアドレス。 ポインタの値としては同じ値だが、意味が違う。 なんか思い違いをしてる気がするぜよ
620 名前:615 mailto:sage [2007/12/15(土) 12:48:40 ] >>618 多次元配列も、型と先頭アドレスと要素数を何らかの形で渡せばいいわけだから、 アドレスに関しては配列名のみを渡せばいいんじゃないの? >>619 意味の違いは理解してるつもりだが、これじゃなきゃできない、というケースが思いつかなくてさ。 先頭の要素のアドレスと、配列そのもののアドレスが違うことがあれば理解もできるってもんだが…
621 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 13:12:30 ] &つけようがつけまいが 値同じだから意味は同じ しょうもねー議論してるんじゃねーよw
622 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 13:22:07 ] そんな乱暴なw
623 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 13:54:30 ] >>621 型が違うから意味は違うだろ
624 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 14:29:01 ] >>621 おまい、ポインタはvoid*さえあればいい派だなw
625 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 14:51:34 ] void *と void **あれば何もいらねーだろ。 型に束縛される書き方してると 汎用性失う言語だし 携帯のドライバなんかは int Inithoge(void * data1, void *data2, void *data3) こんなの普通だぞ?
626 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 15:01:07 ] 携帯用のドライバなんかどうでもいい
627 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 15:42:40 ] www.kouno.jp/home/c_faq/c6.html#18 >>配列の配列は、ポインターへのポインターに成り下がることはない。 これを読んで思ったんだけど、 int main(int argc, char **argv)は間違い(行儀が悪い)で、 int main(int argc, char *argv[])が正しい(行儀が良い)の?
628 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 16:43:52 ] >>627 関数の引数は常にポインタしかとらない。 字面上配列の形をしていても、そいつはポインタだ。 だから、 void foo(char *pa[]); void bar(char **pp); char aa[10][10]; という関数と配列の配列があったとして、以下の呼び出し foo(aa); bar(aa); のどちらも違法(コンパイラが怒る)だ。 これが「配列の配列は、ポインターへのポインターへ成り下がることはない」の意味だ。 ちなみにmainに渡されるargvはポインタの配列であり、これはポインタのポインタで受けられる。
629 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 18:02:39 ] argvがポインタの配列だから void hoge(char str[])を void hoge(char *str)と書けるのと一緒で int main(int argc, char *argv[])を int main(int argc, char **argv)って書くのは全然おかしくないわけか。 むしろ後者の方が実際にやっていることとイメージが近いな。
630 名前:デフォルトの名無しさん mailto:sage [2007/12/15(土) 18:45:17 ] const char* const argv[] って書きたいところだけど
631 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 06:01:17 ] ポインタの配列と、配列の配列の違いを、 いくら説明しても全く理解できないヤツ、 会社に一人くらいいるよな・・・ プロのプログラマーのはずなのに
632 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 06:05:55 ] ・ポインタを「何かを指している矢印」 ・配列を「何かが入っている箱」 という図を描いてみて、その上で配列の配列とポインタの配列を描いてみればすぐわかると思うんだけどな。
633 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 11:13:25 ] >>631 専門書籍で使われてる言葉をそのまま使っても伝わらないよ 一度日本語に直す、相手に伝わる言葉に直す そういうリファクタリングを繰り返してバカ矯正プログラムが完成するんだ
634 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 16:47:55 ] ダブルポインタと呼ぶのはやめてほしい
635 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 17:07:40 ] 図ばかり頼りにして、言葉を大事にしないのは、理系プログラマの欠点だ
636 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 21:45:05 ] 文章から何かをイメージする能力が読む側に備わってない 理系文系だ関係なく読解問題が苦手なの増えてるだろ? だからこっちでイメージを用意してやりようやく相手が理解できる マンガと同じだわ
637 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 22:15:45 ] そうゆうこと 嫌韓を読めばよくあの国が理解できるのと一緒
638 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 22:49:12 ] 嫌韓って漫画じゃねえよあれ。カット集じゃん 全編挿絵っつうか
639 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 23:05:44 ] マジレスすること自体 ゆとりだと自己主張しているものだな。 このスレ削除でよくねーか?
640 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 23:08:20 ] 時々思いがけない議論があってちょっと楽しいから 削除しないで放置しておいて欲しい
641 名前:デフォルトの名無しさん mailto:sage [2007/12/16(日) 23:13:43 ] マジレスでもなんでもないだろw どんどん話題が枝葉にそれてるだけで
642 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 00:08:20 ] まず、学ぶべきことを定義するのが先じゃないか? アドレスの代入、アドレスが示す値の参照 関数へのアドレス渡し ポインタを利用するアルゴリズムを理解 こんな感じでさ
643 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 00:14:32 ] レス600過ぎてから定義されてもwww
644 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 01:39:57 ] 老いて益々盛んってことわざもあるし 人生に手遅れって言葉はないと思うんだ
645 名前:デフォルトの名無しさん [2007/12/17(月) 04:57:57 ] w w
646 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 11:54:52 ] 図に書いて説明するより、ソースレベルデバッガでポインタ変数にどんな値が入って、 その値が指すアドレス(とその前後アドレス)にどんな値が入ってるのか 見せた方が分かりやすいと思う。
647 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 12:32:54 ] >>646 ポインタの実際の値がいくつなんて、 どうでもよいことじゃね?
648 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 17:17:05 ] ポインタをsizeofすると正体がわかるよね 32bitの処理系なら型に限らず全部4だし
649 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 18:12:01 ] >647 いや、そういう正体のつかめ無さが、初心者には分かりづらいんじゃない? まずは抽象度を下げて、具体例から入った方がいい。
650 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 21:20:39 ] >>648 ただそんなことに頼っていると書いているコードがしばらくたって 使おうと思うと動かなくなる。
651 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 23:40:06 ] ポインタは単純だ for (int i = 0; dst[i] = src[i]; i++); がポインタのおかげで for (; *dst++ = *src++;); できるだけだ
652 名前:デフォルトの名無しさん mailto:sage [2007/12/17(月) 23:59:44 ] あまり違わない気がする・・・
653 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 02:16:14 ] つか、C++使い始めてからポインタなぶるなんて中々無くなったわ
654 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 02:48:13 ] 関数での受け渡し以外にポインタなんて使う?
655 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 03:51:26 ] mallocなどで確保するときに使うよ
656 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 09:50:06 ] 文字列だってポインタじゃん
657 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 18:39:02 ] >>654 自己参照型構造体使ってないのか?素人さん?
658 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 20:34:35 ] 玄人さんがお見えになったぞ!
659 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 20:48:28 ] ポインタ使うのに、玄人も素人もない
660 名前:デフォルトの名無しさん mailto:sage [2007/12/18(火) 23:03:10 ] グローバル変数の初期化順序が保証されてないから、初期化順が重要な グローバルオブジェクトはポインタだけ定義しといて、初期化関数で順番に newしていくとか。 (順序が重要なオブジェクトをグローバルにすることの是非は置いといて)
661 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 01:03:25 ] >>654 オブジェクトいろいろ弄る時に使うよ。入れ替えたりとか便利。
662 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 01:33:28 ] コールバックするのにつかうー longjumpするのにも使う
663 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 01:43:57 ] もう「無いと困る」でいいんじゃね?
664 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 01:51:40 ] >>657 データ格納するならデータベース使わね? 組み込みなら、一時的な(親機に渡す日次処理で消えてしまうよな)データの格納に使ったりするけど 今は組み込みもDBの採用が進んでるし
665 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 01:55:29 ] それとこれとは話が違う・・・
666 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 02:02:54 ] 話が違うというか、本物が来ちゃったようだ・・・
667 名前:デフォルトの名無しさん [2007/12/19(水) 02:37:02 ] ポインタ使って2−3木を作りたいと思っているのですが ここを見ればおkていうサイトとかありませんか?
668 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 08:24:16 ] データ構造とアルゴリズムを扱った書籍を買った方がいいと思うね
669 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 10:32:47 ] てか作ればいいじゃん
670 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 10:48:42 ] 自己参照構造体というのを試してみたんだが、メモリの開放が面倒そうだ。 自分を指してる一つ前の構造体のアドレスってどうやって取得するの? 元々そういう風に構造体を作らなきゃダメ?↓みたいな感じで。 typedef struct tree { struct tree *prev; struct tree *next; int x; } tree_t;
671 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 10:51:29 ] 駄目
672 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 10:59:19 ] 自分は初期の頃はtree->next->nextでNULL見つけてtree->nextを解放したら, tree->nextをNULLにする.ポインタ最初に戻してまた上から見るみたいなことやってたw 双方向だとその辺ずいぶん速くなるよね.
673 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 11:32:57 ] >>672 再帰すればいいじゃん。
674 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 11:44:48 ] >>672 うん,いまは順方向だけの場合そうやってる. 順j方向リストの場合サーチかけてるポインタじゃなくて その次に対して操作すると一つ前のアドレスはサーチかけてる ポインタそのものになるということをいいたかった.
675 名前:デフォルトの名無しさん [2007/12/19(水) 12:56:15 ] >>668 >>669 わかりました、頑張ります!
676 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 13:35:02 ] おまいら、1方向の線形リストならもっとうまい手があるだろうが。 あるノードを消す場合は、その後ろのノードを消すノードに上書きして、 後ろのノードをfreeするんだよ。
677 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 17:35:31 ] 一方向の線形リストなら「上書き」って必要ないでしょ 消すノードの前のノードと後ろのノードを繋げてから 対象ノードをfreeすればいいんじゃないの
678 名前:676 mailto:sage [2007/12/19(水) 17:39:23 ] 1方向って*prevがないやつか ごめんなさい
679 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 17:39:55 ] おれ677だった ごめんねごめんねごめんね
680 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 17:56:32 ] >>679 許すからキニシナイ。 真面目な話、あるノードを消したければ後ろのノードの内容を上書きして後ろの方の ノードを消すなんてのは一方向線形リストを扱う時の基本的なアルゴリズムだよ。 先頭からまた検索するなんて、無駄無駄無駄〜! じゃ、あるノードの前に新しいノードを追加する時はどうすれば無駄がないか 考えてみそ。
681 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 19:19:59 ] ポイントを押さえて学ぶべき
682 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 19:57:24 ] 2次元配列を渡すときに大きさが分からなくて void hoge(int array[][SIZE])見たいな書き方ができないときは void hoge(int* array[])か void hoge(int** array)で書くしかない?
683 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:00:19 ] 動的確保してポインタへのポインタで渡す
684 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:19:36 ] 動的静的関係なくね?
685 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:22:04 ] 渡す側がサイズを知らないってどういうこと?
686 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:26:19 ] よくあること
687 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:30:01 ] >>682 また、ポインタと配列がゴチャゴチャになってしまって分からないヤツがきたな
688 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:30:38 ] 受け取る側が渡す側からサイズを教えてもらえないと、2次元として扱うのは無理なのだが
689 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:31:15 ] 番兵くんがいればそうとも限らない
690 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:40:50 ] もう、なんでもかんでもvoid*で渡して、 後は、渡されたほうの関数の中で好きにすれば、 なんでもOKだ
691 名前:682 mailto:sage [2007/12/19(水) 20:46:15 ] int sum(int** array,int i_size,int j_size){ int sum=0; for(int i=0;i<i_size;i++) for(int j=0;j<j_size;j++) sum+=array[i][j]; return sum; } a[3][4],b[10][20]が宣言されてたとして、 上の関数ならsum(a,3,4)もsum(b,10,20)も実行できるけど *じゃなくて[]を使おうとすると大きさ分からなくて困るじゃん… と書こうとしたんだが、静的配列じゃ動かないのなこれ。 いろいろ勘違いしてたすまん。
692 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:49:02 ] malloc()したときに確保した要素数わかってるんだから、 それを関数に渡せばいいだけだと思うが。 要素数を教えないで、どうやって終端を認識するの?
693 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 20:58:44 ] void hoge(int **ary, int m, int n) { /* ごにょごにょ */ } int main(void) { int **ary; int m, n, i; /* m, nに配列長を代入 */ ary = malloc(m * sizeof(int *)); for (i = 0; i < m; i++) ary[i] = malloc(n * sizeof(int)); return 0; } こういうことじゃないの?
694 名前:デフォルトの名無しさん mailto:sage [2007/12/19(水) 22:23:32 ] 配列でもポインタが扱える では無く、むしろ 配列はポインタで処理される と考えるんだ
695 名前:デフォルトの名無しさん mailto:sage [2007/12/20(木) 00:33:27 ] つか、STL使えよって話だよな
696 名前:デフォルトの名無しさん mailto:sage [2007/12/20(木) 20:29:52 ] OTLもなかなかいいよ
697 名前:デフォルトの名無しさん mailto:sage [2007/12/20(木) 20:36:39 ] ポインタの壁に挫折した人みたい
698 名前:デフォルトの名無しさん mailto:sage [2007/12/21(金) 04:26:47 ] いろいろ書いて実行してみること。 アセンブラしてたからかな?すぐ理解できた。
699 名前:デフォルトの名無しさん mailto:sage [2007/12/21(金) 09:21:28 ] 今からポインタ学ぼうって人が「じゃあアセンブラからやろう」って思う訳が無い
700 名前:デフォルトの名無しさん mailto:sage [2007/12/21(金) 12:01:32 ] アドレス変換テーブルの話なんか聞かされて よけいわけわからなくなっちゃったような奴なら じゃあアセンブラからやろうと思うんじゃないか
701 名前:デフォルトの名無しさん mailto:sage [2007/12/21(金) 14:13:17 ] やる気さえあればすぐ覚えられる 最長でも1日悩み抜けば覚えられるレベル 厄介なのは、すぐ意気消沈してしまう性格
702 名前:デフォルトの名無しさん [2007/12/22(土) 03:07:15 ] ** をポインタのポインタなどと訳する事で余計に初心者の理解を妨げてるように感じる。
703 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 03:11:39 ] じゃあなんて
704 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 03:29:18 ] ポインタ(変数|オブジェクト|インスタンス)へのポインタ
705 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 03:34:15 ] ようするにポインタへのポインタじゃないか
706 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 11:26:22 ] pointer to pointer 「の」は適切じゃないかもな
707 名前: mailto:sage [2007/12/22(土) 11:26:53 ] ポインタ変数を型とするポインタとか
708 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 11:35:30 ] >>707 わけわからん
709 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 12:45:55 ] toに引きずられてるアホども
710 名前:デフォルトの名無しさん mailto:sage [2007/12/22(土) 13:05:50 ] ポインタとポインタでいいじゃん 2こ仲良くていいじゃん