1 名前:デフォルトの名無しさん [2010/06/30(水) 10:22:47 ] なぜポインタで引っかかる人が多いのか 引っかかる人は何に困惑しているのか
133 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 12:57:03 ] 対象者が何につまずいているのかを想像する能力がなければ、 真の意味で教えることは難しい。 教える側に対象者のつまずきを理解する能力が無い場合、 対象者が理解できるかどうかは対象者の能力に依存する。
134 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:09:12 ] >>133 そうだな 簡単な話が理解出来ないのは 耳が悪いのかも知れないし そもそも話を聞いてないのかも知れないし 頭が悪いのかも知れない
135 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:17:00 ] ポインタは正常に動くのにたまに変になることがある int a[10]; a[10]=100; みたいにやると、稀におかしくなる コンストラクタとかifとかで複雑になってくると よく見ると int * p; *p=100; みたいなことを平然とやってたりする。 短いプログラムだとこんなことはしないだろうけど 複雑なプログラムだと初心者はわけがわからなくなる。 これが初心者にとって難しいんだろうな。
136 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:23:07 ] >>135 > a[10]=100; 正常に動くことがあるから、誤解の種になるよね。 必ず異常動作すれば気づくんだが。 char *p="abc"; *p='A'; これが正常に動く環境があって、 しばらく平気でそういう記述してた時期があった。
137 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:30:53 ] char* pの書き方だけは許さない。 こういう書き方をしている人物こそポインタで引っかかったままだと言える。
138 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:31:57 ] >>137 Microsoftのソフト開発者は全員そうだな。
139 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:41:21 ] 結構、ポインタって文法の丸暗記で何とかなったりするからなぁ int (*ptr)[10]; int a[100]; //mallocの代わり ptr = (int (*)[10])a; ↑これを理解するのに結構時間かかった、特に関数の引数にしたときとか アドバイスもらって、アセンブラ入門を勉強したら理解できるようになったんだよな 多分、実際のメモリ範囲確保とインデックスによるアドレス指定が理解の助けになったと思う
140 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:44:58 ] >>137 char *p[10]; char (*p)[10]; *がpに付くのなら上記は同じ意味になるだろう。 *が宣言に付くからこそ(*p)とすることで違う意味になる。 そういう意味からは char* p; のほうがしっくり来る。 俺は char *p; と書くけどね、char* p0,p1; のことがあるからね。
141 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:46:46 ] やたら記述にこだわってて内容理解してそうにない書き込みが多いところが恐怖
142 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:48:30 ] C#では int* p,q,r; ってやったらpもqもrも CやC++でいう int *p,*q,*r; みたいに、全部が*つけたようになるな アンセーフモードでしか実行できないけどね Microsoftのポインタに対する意識が明確に現れてるな
143 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:58:02 ] >>126 第一印象に敏感な人は重症化しやすい、という意味では大事かもしれないが 本来は、印象なんてあやふやなものには鈍感なほうが良い >>141 上のほうで、文法より意味を考えようぜっていう正論が出たから 逆の書き込みをすれば色々釣れるだろうと思ってるのかもしれん
144 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 13:58:46 ] char *p; char (*p); 上記は同じものを指すが、結果として同じものをさすだけであって、 その意味合いは異なる。 前者は"char*型のpの宣言"であり、 後者は"pはポインタであって、そのポインタはcharを格納するアドレスのポインタ"。 それが理解できなければ、 char *p[10]; char (*p)[10]; は理解できない。
145 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:03:27 ] ホント記述弄り好きだな こんなの覚えてもしょーがねーだろ
146 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:09:25 ] >>145 しょうがなく無いぞ char *p[10]; char (*p)[10]; どっちの意味でも使うことあるから。 宣言の*が型に付くことを知っていれば、 前者のpが配列、後者のpがポインタだと理解しやすい。
147 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:14:23 ] int a[10][10];
148 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:19:29 ] それは別にポインタが難しいからじゃなくて、C言語が難しいから。 文法云々というか、プログラマの責任がデカい部分。
149 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:23:31 ] >>146 *(p[10]) か (*p)[10] かの違いだよ。前者の括弧は冗長だから書かないだけ。 *は前置単項演算子だから、被演算子は常に後ろに付く。型に付くことはない。
150 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:42:16 ] なにいってるんだ int * p の*は演算子ですらないぞ *p=&x みたいのでpの←の*は演算子だけど。
151 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:47:48 ] >149 知ったかは口はさむな
152 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 14:55:06 ] 説明する能力がなければ、真実を伝えることが難しい例。 説明する能力があれば、真実でなくても実質問題の無い考え方を伝えることが出来る例。
153 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 15:26:43 ] mallocだのなんだの使うより new int のほうがわかりやすいよね
154 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 16:57:46 ] >>144 意味合いも型も全く同じ。 どちらも*演算子を適用するとcharになる。 >>146 の意味合いは演算子の 結合が異なるから意味が異なって当然: ・char *p[10] =>char *(p[10]) => pに[]したあと*すればcharになる ・char (*p)[10] => pに*したあと[]すればcharになる 変数の記述と同じように演算子を適用したら、 最終的に一番左に書いたcharやらが取得できるのがポインタの文法。
155 名前:デフォルトの名無しさん mailto:sage [2010/07/04(日) 23:34:12 ] ポインタで引っかかる人が多い、というより Cのポインタで引っかかる人が多い、の方が正確だろうな。 C以外でポインタで引っかかる人の話はほとんど聞かない。 Cのポインタも、言語規格を読めば別に難しくないが、直感では理解しにくい。
156 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 00:47:28 ] とりあえず複数変数宣言を一行でやるのやめろや・・・ 見づらくて仕方ない。
157 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 00:52:23 ] >>131 あってないだろ *pが変数名ならポインタ使用するときpって書くなよ *とpを分解するなよ *とpがくっついて初めてIDなんだろ?って思った あくまでpはchar*型の変数だろ だから*演算子でポインタpの値参照できるんだし
158 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 01:15:16 ] ↑ char *p *pはchar型であってるよ *pは変数名じゃないよ pが変数名だよ。
159 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 01:30:09 ] char * p 「char型」の「ポインタ(*)」の「変数p」と言った方がいいかな。
160 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 01:41:40 ] *pの型がcharとかは関係なくて char *p;で宣言される変数はp てだけだろ。 *pは宣言されてない。 配列とかでも同じだからなぁ。 特に分かりづらいと思ったことなかった。
161 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 03:57:28 ] 幅WID, 高さHEIのint型の二次元配列arrayを動的に確保したい。 1)arrayの宣言文を書け。 2)arrayのメモリ確保文を警告レベル最大でも警告が出ないように書け。 3)arrayの要素アクセス方法、具体的にはarray中の横からw番目、縦にh番目の要素に0を代入する文を書け。
162 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 06:43:49 ] >>159 char*型の変数pでいいよ。 変数名取り除いたのが型の名前だし。 >>161 とりあえずC99禁止しようか。
163 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 07:37:57 ] >161 二次元配列ってなんだ 配列の配列か 一次元的に取られたメモリを工夫して二次元的に扱える形にしろというのか 一次元的に取られたメモリを工夫して三次元的に扱える形にしろ ただし、外側から縦、横、奥を表すとし、メモリの確保は1回で実行せよ また、型は適当なものをtypedefし、type_t型として作成せよ ただし、縦、横、奥は実行時に与えられ、特定のtype_t型に依存するコードは書いてはならない 縦、横、奥はsize_t型を仮定してよいものとする 全ての縦、全ての横、全ての奥のアドレスに対してそのアドレスがそのアドレス以外のものと異なるようにせよ 全ての縦、全ての横、全ての奥の要素に対して任意の値を代入し不正なメモリ書き換えが行われないようにせよ メモリの確保には標準関数のvoid *malloc(size_t)を使用せよ ここで、言語仕様はC89またはC90を仮定してよいものとする ただし、コンパイラの拡張を使用することを禁止する 例 : type_t ***array3; array3 = alloc3(h, w, d); array3[h][w][d] = val;
164 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 08:05:39 ] 前の問題の答も出さずに勝手な問題積み上げてバカじゃないの
165 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 11:18:28 ] スレタイとは何の関係もない話題になった。
166 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 15:19:30 ] *********************************************p
167 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 16:37:36 ] *は2つあれば十分 3つ以上使うコードがあっても、void**とキャストを使うコードに変換できる
168 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 16:46:54 ] 変換できることに意味はないな。適当にtypedefし直せば充分。
169 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 16:57:39 ] バイナリエディタで機械語書かせれば一発で理解できると思うんだ
170 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 17:15:05 ] 誰も>>161 には答えられない、と。
171 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 17:21:17 ] 興味が無ければ答えない。当たり前だと思うが。
172 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 17:24:00 ] 今まさに仕事でその手のコードを書いているからめんどくさいw CPUとGPUの違いやsimdの演算効率の違いを考慮して、 AofSとSofAを切り替えたりxyzの順序を変えたりの詰め替えばっかりw
173 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 18:09:33 ] >>170 配列へのポインタでいいのか?
174 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 18:32:08 ] >>161 1) int *array; 2) array = (int*) malloc(sizeof(int) * WID * HEI); 3) array[h * WID + w] = 0; Java使いでちゃんとしたCのコードなんか書いたことないんだけど、 これでいいのかな?このスレにいる詳しい人添削頼む。 あと>>163 も同じように処理しちゃまずいのかな。
175 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 18:52:55 ] >>174 2次元配列と書いてるから、array[WID][HEI}の形にしないと駄目だろうね >>161 の条件だと↓でもよさそうだけど、>>163 はひと手間かけないといけない int (*array)[HEI] = (int (*)[HEI])malloc(sizeof(int) * WID * HEI);
176 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 18:56:41 ] 一回でメモリ確保せよとはあるけど必要充分にとは書いてないから、 3次元分のメモリとポインタ分のメモリを確保してポインタの配列をこさえればいいんだけどね。
177 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 22:16:21 ] >>163 >ただし、縦、横、奥は実行時に与えられ、特定のtype_t型に依存するコードは書いてはならない これは↓がだめだという意味? typedef char (*type_t)[w][d]; type_t array = (type_t)malloc(sizeof(int) * h * w * d);
178 名前:177 mailto:sage [2010/07/05(月) 22:17:04 ] 1行目 typedef int (*type_t)[w][d]; ね。
179 名前:デフォルトの名無しさん mailto:sage [2010/07/05(月) 22:27:24 ] typedefしなくていいのなら、 for文で回しながらmallocして、 for文で回しながらfreeすれば出来そうだけど。 (そこまでするんならいっそ1次元でとって、添え字演算したほうがすっきりしそうだが・・・) >>163 は出来るのかね。
180 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 02:01:16 ] kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10787.txt 自分で書いていて途中で嫌になってきた typedefを使わないとほとんど読めないプログラムになってしまうのが ポインタの問題だな 関数へのポインタの配列へのポインタを返す関数 (関数は配列を返す事ができないので配列へのポインタで返す) でも無駄な事を一段やってるような気がするな 配列だと分かっているんだから配列を変えそうとせず、ポインタで配列の 先頭アドレスを返せば簡単になるような気もする
181 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 02:16:07 ] いや違うかこれ以上簡単にならんな 関数は配列を返す事が出来ないんだから、配列へのポインタを 返すと書かなければならない 本当はそうではないのだが、Cの文法がそう書く事を許さない仕様に なっている こういう場合は関数宣言の方を変えて、配列を返すのではなく関数への ポインタのポインタを返すと書けば簡単になるだろう 但しそう書くとプログラムが何をやっているのかますます不明瞭になり、 ほとんど読み解く事が困難になってしまう
182 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 02:20:23 ] kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/img/10788.txt こんな感じ これなら一段間接参照が減る さて寝よう
183 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 08:36:52 ] array[h * WID + w]でいいよ ひとつ言えることは ポインタで引っかかる人は、文法や型にこだわる 問題を出されると出題者に盲従する傾向がある だったら、文法や型や規格書などに従うのを一度やめてしまえばいい たとえばアセンブラを使ってみるとか
184 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 10:38:36 ] それでいいなら、int array[W][H];も必要ないね
185 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 10:46:20 ] [W][H] じゃなくて [H][W] だというところには誰も突っ込まないんだなw
186 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 10:57:25 ] 言いたいことそんな所じゃないだろうからな。
187 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 10:58:23 ] メモリのスキャン方向が変わるから実行速度等に影響が出るんだが
188 名前:184 mailto:sage [2010/07/06(火) 11:56:51 ] >>175 から持ってきて、あんまり考えずに成形しただけだから気にするな >array[h * WID + w]でいいよ だけだったら異論はないよ あとあと、楽とわかってるから静的に2次元配列として宣言するんだよね 動的確保でも、その楽にする方法があるから、(言い方を借りれば)文法にこだわるんじゃないか まぁ、これも>問題を〜の1文がなければ、そうですねって話だけど
189 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 11:57:59 ] >>79 俺と全く同じ奴がいる・・・
190 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 12:33:04 ] >>184 array[WID][HEI] と array[h * WID + w] は等価ではない
191 名前:184 mailto:sage [2010/07/06(火) 12:51:07 ] >>190 なぜ、俺にこのタイミングでレスするんだ 安価は>>175 にしてくれよな
192 名前:デフォルトの名無しさん [2010/07/06(火) 12:56:11 ] アホ曝しage 184 デフォルトの名無しさん [sage] 2010/07/06(火) 10:38:36 ID: Be: それでいいなら、int array[W][H];も必要ないね
193 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 14:40:57 ] >>183 良くない。 array[h][w]という表記ができない言語(例えばアセンブラ)ならそれでもいいが、 言語仕様で出来るのにやらないと、後から読んだ者を混乱させる。 理由があってわざとやらないのか、書いた奴が知らなかっただけなのか判断つかないからな。 それに、hとかwとかなら array[h*WID+w]でもarray[h][w]でも大差ないが、もっと複雑な式に なった時に、[h][w]形式の方が断然読み易くなる。 ぶっちゃけ、二次元ポインタを使いこなせない奴の言い訳にしか見えない。
194 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 15:49:07 ] どうでもいい。 個人的にはベタバッファにポインタアクセスのが分かりやすいし、使いやすい。 C++は知らんがCなら慣れの問題。
195 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 15:58:19 ] array[i][j] と記述したくなるのは、ベクトルやマトリックス周辺だけかな。 数式をそのままに近い形式で記述したい という意図だけどね
196 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 16:09:18 ] 結果あわせるだけならどっちでもいいんだけれども 配列のアライメントや入れ替えがあるから、用途によるよね
197 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 16:42:13 ] >>190 どう等価じゃないんですか?
198 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 16:56:35 ] array[4][5]とarray[5][4]は違うと言っている。
199 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 18:54:32 ] こういう書き方はどうか?(長文失礼) ・char , int は型である。 ・Tが型ならば、T[N]は型である。(Tの配列と解釈する) ・Tが型ならば、$Tは型である。(Tへのポインタと解釈する) ・T,U1,U2,…,Umが型ならば、T(U1,U2,…,Um)という記号列は型である。(関数と解釈する) ・宣言方法は「T a;」とする。 具体例(カッコは適宜省略) C言語での表記法 ↓ ↓ int a; ( int a;という意味) int[N] a; ( int a[N];という意味) (int[w])[h] a; ( int a[h][w];という意味。wとhは逆になる) $int a; ( int* a; ) int(char) func; ( int func(char); ) $($int) a; ( int** a; ) ($int)[N] a; ( int* a[N]; ) $(int[N]) a; ( int (*a)[N]; ) $(int(char)) f; ( int (*f )(char); ) ($int)(char) f; ( int* f (char); ) int($char) f; ( int f (char*); ) ($(int(char)))[N] f; ( int (*f [N])(char); ) ($$(int(char)))[N] f; ( int (**f [N])(char); ) $(($(int(char)))[N]) f; ( int (*(*f )[N])(char); )
200 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:03:33 ] ご苦労さん
201 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:14:30 ] >>193 記述の問題ならマクロ導入すりゃいいでしょう
202 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:17:35 ] まあな。w
203 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:33:38 ] ポインタに1足したら、2byteとか4byteとか進む? ポインタってアドレスなんだろ? そんなもん1進むに決まってるんじゃないのか?
204 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:41:18 ] オブジェクト(要するに型)のサイズ分進む。 sizeof演算子で進む量を得ることが出来る。
205 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 19:58:50 ] >>197 判ってて聞いてるんだろうけど array[h * WID + w] と array[w][h] はポイントしているアドレスが違う array[h * WID + w] と array[h][w] が同じ場所を指さないと 共同開発してる仲間に迷惑だろ? そんなことも知らないからポインタスレに来てるんですねわかります
206 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 20:21:03 ] 前者は連続した領域にmallocすることが求められるが、 後者は離れた領域にmallocしても一向にかまわない。
207 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 20:22:13 ] そろそろ>>163 の見本お願いします
208 名前:163 mailto:sage [2010/07/06(火) 20:58:16 ] >>207 まあ、あせるな みんな、なかなかいい線いってるよ もう少し検討が深まるのを待とう
209 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 21:32:28 ] >>208 これはだめなの → >>177 C89ならw,dが変数でも通ったけど。
210 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 21:41:09 ] >209 >208ではありませんが、コンパイラとコンパイルオプションを示してみてください また、可能であればコンパイラのバージョンも示してみてください
211 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:00:20 ] >>210 PC@Test> gcc --version gcc.exe (GCC) 3.4.5 (mingw special) Copyright (C) 2004 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. PC@Test> gcc -Wall -pedantic -std=c89 Test6.c Test6.c:14: warning: ISO C90 forbids variable-size array `type_t' Test6.c:14: error: variable-size type declared outside of any function Test6.c:14: warning: ISO C90 forbids variable-size array `type_t' Test6.c:14: error: variable-size type declared outside of any function ごめん、今やったら通らんわ。
212 名前:221 mailto:sage [2010/07/06(火) 22:01:09 ] 昨日、下記のソースをいじってら通ったんでC89ならOKなんだと思ってた。 昨日の試行錯誤の過程で勘違いした模様。 #include <stdio.h> #include <stdlib.h> #define MODE (0) #if MODE == 0 int w = 10; int d = 20; #elif MODE == 1 const int w = 10; const int d = 20; #elif MODE == 2 #define w (10) #define d (20) #endif typedef char (*type_t)[w][d]; int main(void) { int h = 30; type_t array = (type_t)malloc(sizeof(char) * h * w * d); printf("%d\n",((int)&array[0][0][1])-((int)array)); printf("%d\n",((int)&array[0][1][0])-((int)array)); printf("%d\n",((int)&array[1][0][0])-((int)array)); free(array); return 0; }
213 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:08:40 ] てか何が出来たら「三次元的に扱え」たコトになるのよ? 条件が色々付いてるけど、根本的な要求が分からん
214 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:11:01 ] 下記のポンタ何を指すが書きなさい 15秒以内の回答できて小学1年レベルらしい int (*a)[N]; int (*f )(char); int (*f [N])(char); int (**f [N])(char); int (*(*f )[N])(char);
215 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:15:02 ] >>214 日本人ではないな? だからどう、ということもないが
216 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:51:32 ] m行n列の二次元配列をメモリ上に表現する場合 1 サイズm*nの一次元配列として確保 2 サイズmのポインタの配列とサイズnの一次元配列m個 1の利点 ポインタの配列分メモリが必要無い 2の利点 列を削除追加できる 2は多段のポインタなので 普通の二次元配列として扱うと遅い 中継用のポインタ使う必要があるので可読性は低い
217 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:53:54 ] 2 はargvですね
218 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 22:57:59 ] 小学生すごいな、即答出来ても15秒で書けないな
219 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 23:01:51 ] >>218 小学生でも朝鮮・中華の小学生だから
220 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 23:07:14 ] >>214 上から順に 行列の行単位で動くポインタ 関数ポインタ ポインタ配列 ポインタ配列 行列の行単位で動くポインタ 行列やポインタ配列の要素の型、つまりテンプレート引数に相当する部分は気にしない。 昔のJavaはそうだったというかむしろシンプルでわかりやすいとか言われて普及した。
221 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 23:28:34 ] >>216 >2は多段のポインタなので >普通の二次元配列として扱うと遅い これマジ? ケースバイケースだろうけど、乗算して加算して参照より、 参照してさらに参照のが速いのかと思ってた。
222 名前:デフォルトの名無しさん mailto:sage [2010/07/06(火) 23:43:30 ] >>221 F-22とスピットファイアくらい違う
223 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:00:13 ] >>214 ポンタはわからねえな
224 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:08:27 ] >>223 上から順に ポインタ ポインタ 配列 配列 ポインタ なのは分かるよね。 後は、ポインタだったらポインタの部分を削除して型を見て、 配列だったら配列の部部を削除して型を見る。 そうすると、 配列のポインタ 関数のポインタ 関数のポインタの配列 関数のポインタのポインタの配列 関数のポインタの配列のポインタ となる。 合ってる?
225 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:11:02 ] >>180 の int (*((*func(void))[]))(void) これ鬼みたいだな しかしプログラムを読むと大して難しい事をやっているわけではない Cの宣言はどうしてこんなに難解なのだろうか
226 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:12:49 ] >>222 どっちが速いのかすら分からん。 あー、もしかしてキャッシュに乗らない? あんまりその世界で生きてないんで どう動くのかサッパリ。
227 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:17:46 ] >>225 アセンブリをやれば簡単に読めるようになる
228 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:33:24 ] int (*((*func(void))[]))(void) は保育園レベルでちゅよ この程度すぐに解らんと保育園レベル未満の国語力ってことでちゅ
229 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 00:44:13 ] >>225 リンク先は見てないけど、そんなに難解? ちゃんと()付いてるし。 まず一見してfunc(void)な関数の宣言だろ。 *付いてるから返値はポインタ。 さらに[]なんで配列のポインタ。 次の*で、ポインタの配列のポインタ。 で、最後にint ()(void)なんで、つまりこの宣言は そういう関数へのポインタの配列のポインタを返す、引数voidな関数funcの宣言。 長々書いて違ってたら、凄い恥ずかしいんだが、どないだろ?
230 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 01:14:43 ] >>229 >長々書いて違ってたら、凄い恥ずかしいんだが、どないだろ? どのように解析するか自信ないのか? コンピラー(C言語)の構文解析ルールをよく知らないってこと? コンピラーはfunc(void)が関数の宣言ってどうしてそう判断するん? 職業PGにとって構文解析って基礎中の基礎事項で学校で当然習っているじゃないの それすら知らないのに職業PGやってるって人居ないよね 趣味PGなら自分が必要と感じたら勉強してみるか程度で良いけど
231 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 01:26:06 ] >>221 キャッシュへのプリロードするのに間接参照だと予測不能。
232 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 01:41:39 ] 書き方を修正。「$T」じゃなくて「T$」に変えてみた。 ・char , int は型である。 ・Tが型ならば、T[N]は型である。(Tの配列と解釈する) ・Tが型ならば、T$は型である。(Tへのポインタと解釈する) ・T,U1,U2,…,Umが型ならば、T(U1,U2,…,Um)という記号列は型である。(関数と解釈する) ・宣言方法は「T a;」とする。
233 名前:デフォルトの名無しさん mailto:sage [2010/07/07(水) 01:46:37 ] 以下、具体例。(長文失礼します) 具体例(カッコは適宜省略) C言語での表記法 ↓ ↓ int$ a; ( int* a; ) (int$)$ a; ( int** a; ) (int$)[N] a; ( int* a[N]; ) (int[N])$ a; ( int (*a)[N]; ) (int(char))$ f; ( int (*f )(char); ) (int$)(char) f; ( int* f (char); ) int(char$) f; ( int f (char*); ) ((int(char))$)[N] f; ( int (*f [N])(char); ) ((int(char))$$)[N] f; ( int (**f [N])(char); ) (((int(char))$)[N])$ f; ( int (*(*f )[N])(char); ) $が入ってないものは>>199 と 全く同じになるので省略しました。