C言語なら俺に聞け(入門篇) Part 43
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2009/01/24(土) 19:00:13教えて欲しいのではなく宿題を丸投げしたいだけなら
↓宿題スレ↓へ行ってください。
C/C++の宿題を片付けます 122代目
http://pc11.2ch.net/test/read.cgi/tech/1232001038/
・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
# 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること
# サイズが大きい場合は宿題スレのアップローダ等を利用してください
・開発環境や動作環境も晒すと答えが早いかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。
前スレ
C言語なら俺に聞け(入門篇) Part 42
http://pc11.2ch.net/test/read.cgi/tech/1231180205/
過去スレ
http://makimo.to:8000/cgi-bin/search/search.cgi?q=%82b%8C%BE%8C%EA%82%C8%82%E7%89%B4%82%C9%95%B7%82%AF&andor=AND&sf=0&H=&view=table&D=tech&shw=5000
0153デフォルトの名無しさん
2009/01/27(火) 00:59:47そんな考えがあったら [ ] で配列とポインタを同じように扱えるようにしないって。
0154デフォルトの名無しさん
2009/01/27(火) 01:01:080155デフォルトの名無しさん
2009/01/27(火) 01:01:400156デフォルトの名無しさん
2009/01/27(火) 01:01:43えー、どこが。
それこそ、p[n]と*(p+n)を別にすべきってことじゃん。
0157デフォルトの名無しさん
2009/01/27(火) 01:02:21○別にしとけばよかった
0158デフォルトの名無しさん
2009/01/27(火) 01:02:56作り辛くしてでも分かりやすくしたかったんだろう。
0159デフォルトの名無しさん
2009/01/27(火) 01:03:37ということに当時の人が気付かなかった可能性も
0160デフォルトの名無しさん
2009/01/27(火) 01:04:57願わくばうちの会社に>>114が来ませんように
0161デフォルトの名無しさん
2009/01/27(火) 01:05:01そうじゃないと意味が伝わらない。
0162デフォルトの名無しさん
2009/01/27(火) 01:05:380163デフォルトの名無しさん
2009/01/27(火) 01:06:53お前mallocしたことないの?
0164デフォルトの名無しさん
2009/01/27(火) 01:07:33大丈夫。わざわざITドカタになるってわかってるところへ就職を希望する人なんて、
この不景気でもそんなには居ないでしょ。
0165デフォルトの名無しさん
2009/01/27(火) 01:08:150166デフォルトの名無しさん
2009/01/27(火) 01:08:390167デフォルトの名無しさん
2009/01/27(火) 01:10:04理解できなかった事を今更誤摩化そうとしても遅いよ
0168デフォルトの名無しさん
2009/01/27(火) 01:10:32ポインタは p++ したり *p したりするべきものだ、
と言ってるんだろう。
たとえどんな時でも。
ばからしい話だが。
0169デフォルトの名無しさん
2009/01/27(火) 01:10:44おまえ、関数の引数にポインタ渡したことないの?
それとももしかして、1関数300行くらいにして、全部関数内で処理してるの?
0170デフォルトの名無しさん
2009/01/27(火) 01:11:07とかやってもいい?
0171デフォルトの名無しさん
2009/01/27(火) 01:11:330172デフォルトの名無しさん
2009/01/27(火) 01:12:540173デフォルトの名無しさん
2009/01/27(火) 01:13:15>そもそも、ポインタなんだから、増減して使うのが当たり前なのに
がおかしいって、mallocっていう反例を示して指摘してるのに、なにが言いたいの?
0174デフォルトの名無しさん
2009/01/27(火) 01:15:58->は参照先アドレスが実行時に決まるのに比べて、
. はリンク時に決まるってこと。
0175デフォルトの名無しさん
2009/01/27(火) 01:16:07まずいんじゃね?
0176デフォルトの名無しさん
2009/01/27(火) 01:17:52いえそっちではなく、>>114の話です
0177デフォルトの名無しさん
2009/01/27(火) 01:18:41構造体を持つ構造体を、mallocすること考えただけでもそれはありえなくないか?
0178デフォルトの名無しさん
2009/01/27(火) 01:19:34ポインタpの指すアドレスは実行時に決まるのに比べて、
配列arrayのアドレスはリンク時に決まるってこと。
0179デフォルトの名無しさん
2009/01/27(火) 01:19:59インライン最適化されれば配列そのものが使われるかもしれない。
コストを明示したつもりでも、実際コストに差はないかもしれない。
そんなあやふやな意味の無いものを明示する暇があったら
もっと分かりやすく書け。
0180デフォルトの名無しさん
2009/01/27(火) 01:20:42関数内だけで使うローカルな領域をmallocすることなんてそんなに多くないでしょ。
多くは、構造体のメンバとかに置いて、外部とのやり取りに使うためのもの。
だから、後でfreeするための元のアドレスはそのメンバが持っていて
個々の関数ではその値のコピーを使って操作することの方が多いでしょ。
いや、(コピーじゃなくて)直接使うケースが少ないとは言わないけどさ。
で、まあ、確かにローカルで使用するにしても
不定長のバッファなんかは必要ではある。
ただ、この用途は(C++で済まんが)vectorばっか使ってるから
malloc(operator new)することなんか殆ど無いし。
特に、配列として確保したもの(1個のオブジェクトではなく)は
ループを回したりするわけだから、コピーしてレジスタ割付なんかも期待したいところ。
そんな変数を増減するのは、ちっとも不思議じゃなく当たり前の話じゃないかね。
0181デフォルトの名無しさん
2009/01/27(火) 01:20:50簡略化した説明なので、そこまでは勘弁ね
0182デフォルトの名無しさん
2009/01/27(火) 01:22:00それは配列とポインタの違いであって*(p+n)とp[n]の違いじゃないと思うんだが
0183デフォルトの名無しさん
2009/01/27(火) 01:25:51配列(の先頭アドレス)は「定数」だから、コンパイル時に決まる。
それがグローバルかスタックフレームの相対アドレスか構造体内のオフセットかはともかく。
一方、ポインタは「変数」だから、(レジスタ変数にされない限り)メモリを読み出して
その値を得、それにオフセットを加えて参照先を決定する必要がある、ということ。
0184デフォルトの名無しさん
2009/01/27(火) 01:26:49C99ではそうではないとか言い出してみる
0185デフォルトの名無しさん
2009/01/27(火) 01:27:13>>182
>>183
理解できたと思いますが
要するに>>114は何か勘違いしてるってことですか?
0186デフォルトの名無しさん
2009/01/27(火) 01:27:51不思議ではないが当たり前でもないよ
0187デフォルトの名無しさん
2009/01/27(火) 01:29:29で?
0188デフォルトの名無しさん
2009/01/27(火) 01:29:34日本語力の無い俺には>>114をよく読むほど意味がわからなくなってきたw
少なくとも、*(p+n)とp[n]には見た目以外の違いは何も無いよ。
0189デフォルトの名無しさん
2009/01/27(火) 01:31:27つーか普通に関数呼び出しの時にアドレス決まるんじゃないの?
グローバル変数以外
0190デフォルトの名無しさん
2009/01/27(火) 01:32:15増減すること自体は誰も否定してないだろ。
0191174
2009/01/27(火) 01:34:09->は. より間接参照が1回多い分コスト高だってこと。
0192デフォルトの名無しさん
2009/01/27(火) 01:35:54ポインタでアクセスしようが一緒。
0193デフォルトの名無しさん
2009/01/27(火) 01:38:14【初心者お断り】ガチ規格準拠C専用スレ Part133
http://pc11.2ch.net/test/read.cgi/tech/1201153965/
0194デフォルトの名無しさん
2009/01/27(火) 01:40:59何言ってんだ。
後で触れているという点は除くにしても、話の流れ的に
p[n]や*(p+n)として使うくらいなら、pを増減する方が普通ということだろ。
特にわざわざそのためだけに添え字変数を用意するくらいなら。
もちろん、配列として確保したメモリ限定の話な。
0195デフォルトの名無しさん
2009/01/27(火) 01:41:54その点を否定している人は誰もいないと思われます。
0196デフォルトの名無しさん
2009/01/27(火) 01:42:56ね え よ
0197デフォルトの名無しさん
2009/01/27(火) 01:44:04配列とポインタの違いはわかってますよね?
>>196
初心者スレですもんね。
0198デフォルトの名無しさん
2009/01/27(火) 01:45:23もちろんわかってますよ
0199デフォルトの名無しさん
2009/01/27(火) 01:46:55そりゃ (* hoge).なにか
と等価なんだから当たり前だろ・・・・・・・
0200デフォルトの名無しさん
2009/01/27(火) 01:47:35じゃあ>>191の内容はわかってますよね、当然。
0201デフォルトの名無しさん
2009/01/27(火) 01:49:09手に持ったゴミを焼却炉に放り込むときに「燃やす」、
ごみ箱の中身を放り込むときに「焼却する」と言い換えてるようなものだ
0202デフォルトの名無しさん
2009/01/27(火) 01:49:13わかってますよ、自分の発言ですから。
0203デフォルトの名無しさん
2009/01/27(火) 01:52:38コストが違うこともわかってますよね?
それと、p[n] と *(p+n) は全く同じ、ということをあわせて
敢えて違うということを明示するという意図(それに意味があるかはともかく)もわかりませんか?
0204デフォルトの名無しさん
2009/01/27(火) 01:54:38だからそれがバカなこと以外の何物でもないとずっと言ってるんだろうが
0205デフォルトの名無しさん
2009/01/27(火) 01:56:26コーディングした人の好みの問題ですよね、わかります。
0206デフォルトの名無しさん
2009/01/27(火) 01:57:41A. たいていは大きな配列の中をアクセスしてまわるのにポインタを使うほうが、
配列の添字を使うより高速であるが、その反対のプロセッサも存在する
(よくできたコンパイラならどちらの記法を使って書かれたコードにも
良質なコードを生成すべきである)。
CFAQ 20.14
0207デフォルトの名無しさん
2009/01/27(火) 01:58:24単純な増減だけでしかアクセスしないんならそれでもいいかもね。
0208デフォルトの名無しさん
2009/01/27(火) 02:00:59としたとき
for (i = 0; i < 1000; ++i)
for (j = 0; j < 1000; ++j)
a[i][j] = i * j;
より
for (i = 0; i < 1000; ++i)
for (j = 0; j < 1000; ++j)
a[j][i] = i * j;
のほうが遅いらしいんですがなんでですか?
0209デフォルトの名無しさん
2009/01/27(火) 02:01:41char *strcpy(char *dst, const char *src) {
char *top;
while (*dst++ = *src++);
return top;
}
なんてのが「普通」「読みやすい」なんて全然思わない。けど、
char *strcpy(char *dst, const char *src) {
char *top = dst;
while (*src) {
*dst = *src;
++src, ++dst;
}
*dst = '\0';
return top;
}
のような使い方のほうが
char *strcpy(char *dst, const char *src) {
int i;
for (i = 0; src[i]; ++i) {
dst[i] = src[i];
}
dst[i] = '\0';
return dst;
}
よりも「普通」だと言いたいわけよ。
もちろん、この場合に速くなるなんて思わないけど(レジスタ変数が2つまででなければ)。
0210デフォルトの名無しさん
2009/01/27(火) 02:01:58統一的で読みやすいコードを書いてほしい
0211デフォルトの名無しさん
2009/01/27(火) 02:03:25条件の後出し乙
0212デフォルトの名無しさん
2009/01/27(火) 02:03:30右側の[ ]の添え字を1ずつ動かしたものは、メモリ上連続しているので、
キャッシュメモリの効果が出やすい。
左側の[ ]を動かすと、メモリのあっちこっちに飛んでアクセスすることになるのだ。
0213デフォルトの名無しさん
2009/01/27(火) 02:04:070214デフォルトの名無しさん
2009/01/27(火) 02:04:19さすがにそのレベルだとどれでも読みやすさに大差ないだろ
ポインタ演算にしたせいで糞読みづらくなるのはもっとさぁ
0215デフォルトの名無しさん
2009/01/27(火) 02:05:23i 消滅させてくれたはずなんだよなぁ、コンパイラさまの力で
ソース出せといわれても困るけど
0216デフォルトの名無しさん
2009/01/27(火) 02:07:05ありがとうございます
説明にくわえ、キャッシュメモリという単語をもとにおおむね分かりました
どうもありがとうございます
0217デフォルトの名無しさん
2009/01/27(火) 02:08:09どう見ても特殊な状況だけを取り出して「普通」ってw
配列の使い方がそんな単純なものだけなわけねーだろ。
0218デフォルトの名無しさん
2009/01/27(火) 02:10:47あれ、>>114の言っていることがわからないって言ってた(>>188)んじゃなかったの?
じゃあ「>>114の意味がわからない」なんて書かないでよ。
せめて「>>114は無意味としか思えない」とかにしてよ。
すげー時間無駄にしたよ。
本当に日本語苦手なんだろうけど
「日本語が苦手なんですけど」と書き出されても
「初心者ですけど」と言って質問する人と同じように応対すべきとは思わないじゃん。
0219デフォルトの名無しさん
2009/01/27(火) 02:12:26俺はそんなこと一言も言ってない
ID出ない板で勝手に特定の発言を同一人物だと思わないこと
0220デフォルトの名無しさん
2009/01/27(火) 02:14:16って思っちゃったんじゃね?
0221デフォルトの名無しさん
2009/01/27(火) 02:15:060222デフォルトの名無しさん
2009/01/27(火) 02:15:46>>188は別人なの?
>>188は
>>>114をよく読むほど意味がわからなくなってきたw
と書いてあるけど。
0223デフォルトの名無しさん
2009/01/27(火) 02:19:50いや、>>114はポインタと配列のコストの違いと言っているのか、
*(p+n)とp[n]のコストの違いと言っているのか、どっちなのかわからなかったのだ。
あと、>>204は俺じゃないよ。
いずれにせよ、ごめんね。
スレも無駄に消費してごめんなさい。
0224デフォルトの名無しさん
2009/01/27(火) 02:23:32しかし常に*(p+n)と書くというのはあまりにも迷惑すぎる
0225デフォルトの名無しさん
2009/01/27(火) 02:23:49まあ張り付き方見てればわかるけど
0226デフォルトの名無しさん
2009/01/27(火) 02:24:23さすがにそんな奴居ないだろ。
0227デフォルトの名無しさん
2009/01/27(火) 02:27:03>>114
0228デフォルトの名無しさん
2009/01/27(火) 02:28:430229デフォルトの名無しさん
2009/01/27(火) 02:30:040230デフォルトの名無しさん
2009/01/27(火) 02:31:30常にでないならその無意味な意図とやらすら成立しないだろう
0231デフォルトの名無しさん
2009/01/27(火) 02:32:280232デフォルトの名無しさん
2009/01/27(火) 02:32:56ポインタと配列が違うことを示すために変えて書いてます!
ってやつが常にそうしないなら逆に大笑いだ
0233デフォルトの名無しさん
2009/01/27(火) 02:33:430234デフォルトの名無しさん
2009/01/27(火) 02:35:320235デフォルトの名無しさん
2009/01/27(火) 02:38:45前後のつながりのわかる文章を書け
0236デフォルトの名無しさん
2009/01/27(火) 02:43:520237デフォルトの名無しさん
2009/01/27(火) 02:44:21プレフィクスでもなんでもつけたほうがまだマシってものだ
0238デフォルトの名無しさん
2009/01/27(火) 02:55:10別の話題に持っていってやろう。
配列として宣言された変数には[]を使い、
ポインタとして宣言された変数には*()を使う、という人はいるはず。
もちろん、それは関数の仮引数に[]を使うというような方法で区別する。
という話題はどうだろう。
http://www.kouno.jp/home/c_faq/c6.html#4
に近い話があるが。
0239デフォルトの名無しさん
2009/01/27(火) 03:02:260240デフォルトの名無しさん
2009/01/27(火) 03:03:11時間かかりすぎる
0241デフォルトの名無しさん
2009/01/27(火) 03:08:06迷惑すぎる。
*()を使って(2文字増やして)得られるものが何一つない。
ちなみに[]と*()は実は記述上完全な同等ではない。
演算子の優先順位が[]のほうが高いからだ。
ポインタと配列を区別したいなどという理由で*()を押し通していると、
(*())とさらに一つ余計な括弧をつけなければならない場面が出てくる。
0242デフォルトの名無しさん
2009/01/27(火) 03:43:42関数内の処理速度に影響があるということ?
配列を渡すと、渡す際のコストは大きくなるけど、関数内の処理は速くなる?
0243デフォルトの名無しさん
2009/01/27(火) 03:47:41それは議論の余地無く完全に間違ってる
0244デフォルトの名無しさん
2009/01/27(火) 04:01:51だが
int *p,q p[q]は問題無いが、*(p+q)は迷惑。p[q]じゃないと殴りたくなる
というか、後世に継承してもらうのは無理と思って欲しい。
ちなみにC++では
Class *p( operator[](int)が定義澄み)
p[2] はコンパイルエラー
(*p)[2] この書き方じゃないとNG
p->[2]なんて書けない。
void *p
p=(void*)(p+3);はコンパイル可能だし警告もおそらく出ない。
p=&(p[3]);は警告が出る筈。
(処理系によってはコンパイルが通らない場合がある。)
こういった微妙な相違はあるな。
0245デフォルトの名無しさん
2009/01/27(火) 04:09:02たとえば、
struct foo { bar_t bar; };
struct foo foo_array[4];
struct foo *foo_ptr_of_array[] = {foo_array, foo_array+1, foo_array+2, foo_array+3};
struct foo *(*ptr_to_foo_ptr_of_array)[] = &foo_ptr_of_array;
struct foo *(*ptr_to_ptr_to_foo) = foo_ptr_of_array;
foo_ptr_of_array[0]->bar = barFoo;
(*ptr_to_foo_ptr_of_array)[0]->bar = barBar;
(*(ptr_to_ptr_to_foo + 0))->bar = barBaz;
さすがに最後はないだろうとは思うけど。
私は、配列なら添え字演算子を使い、ポインタなら間接参照を使うので、
この場合は、2番目を選ぶと思う。明らかに、最後のは、配列をポインタに成り下げているから、嫌だ。
配列は配列。ポインタはポインタです。混同するのはよくない。
ポインタに間接参照を使う理由は、関数の引数やローカル変数が、間接参照をされている場合、
ポインタなので(+1)、それなりの注意をして読んだり書き直したりできる。
たとえば、NULLポインタチェック、アロケートとフリーの対応、リテイン(他のポインタが、同じアロケート先をさしていないか)チェックなど。
(+1 配列もポインタに成り下がれるけどe.g. sizeof(array)/sizeof(*array)当然私は、sizeof(array)/sizeof([0])のほうを使うけど)
0246デフォルトの名無しさん
2009/01/27(火) 04:10:01C++の例なんかむちゃくちゃ言ってるぞwwwwww
0247デフォルトの名無しさん
2009/01/27(火) 04:39:52極めてアルゴリズム的ななコードはそれが公共的なものである
場合、修正加筆し損なって、破損した場合の影響度を考えると最早書け
ないと思ったほうがいいかもな。
0248デフォルトの名無しさん
2009/01/27(火) 07:23:03混同したくないなら名前を変えりゃいいだけだろ。
そんな汚い表記で迷惑かけるのはやめてくれ。
0249デフォルトの名無しさん
2009/01/27(火) 07:34:430250デフォルトの名無しさん
2009/01/27(火) 10:32:46「混同したくない」ではなく「混同するな」といっているんだが。
たとえそれが糖衣構文とはいってもポインタをあたかも配列のように扱うのはプログラマの意図すべきことではない。
間違ったコードが間違って見えるように、ポインタを配列のように表記せずにはじめから間接参照を使うほうが、
プログラマの意図を反映したコードになる。
配列は、固定長のデータやデータ長が既知であるとき、動的メモリ確保に制限があるとき(マシンの構造上、動的にメモリを確保できない)、
そのほか小手先技の実現のためなどに使えばよい。だからこそ、ポインタと配列は、別の表記をしたほうがよい。
配列は、線形的なデータ構造を作るための安価な複合型
ポインタは、柔軟なデータ構造を作るための安価な複合型
>>汚い表記
どこが汚いのかまったく理解できない。
0251デフォルトの名無しさん
2009/01/27(火) 11:08:540252デフォルトの名無しさん
2009/01/27(火) 11:12:04言いたいことはまぁ判ったから、もう少し判り易い例を提示してくれ。
>245だと何が言いたいのか全く判らん。
■ このスレッドは過去ログ倉庫に格納されています