OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

for 文における処理の改善(C言語プログラム)

  • すぐに回答を!
  • 質問No.125717
  • 閲覧数799
  • ありがとう数9
  • 気になる数0
  • 回答数9
  • コメント数0

お礼率 22% (18/79)

はじめまして。panicdjです。

いまCでプログラムを組んでいます。
環境はVC++ver6.0 Win32 Console Applicationです。

以下のプログラムを見てください。

#define X_MAX 10
#define Y_MAX 20
#define Z_MAX 5

int main(int argc , char ** argv)
{

int i, j, k;
int aa[10][20][5];

for (i = 0; i < X_MAX; i ++) {
for (j = 0; j < Y_MAX; j ++) {
for (k = 0; k < Z_MAX; k ++) {
aa[i][j][k] = 10.0;
}
}


return 0;
}


過去のスレッドでポインタ型によるアクセスを
すれば、処理が高速になるとかかれていました。

自分は,for文による繰り返す処理ではなく,
その「ポインタ型によるアクセス」を実装したいのです。

こんな私にアドバイスお願い致します。
通報する
  • 回答数9
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.9
レベル12

ベストアンサー率 40% (201/496)

> C言語などを解説しているサイトでのサンプルコードとかでしょうか??
も、含めてですね。オープンソースなプログラムとかでもよいと思います。勉強の種は沢山転がってますから探してみてください。

> これは、たとえばVCを用いているのであれば、デバッカの
プログラミングの際の話のつもりで書きました。頭の中にメモリのイメージ(箱とか?)を思い浮かべると良いです。今宣言した変数はどこにあるのか、とか、ポインタの先の実体はどこなのかというのを常に意識してということです。

> できることなら、参考になる書籍やサイトを提示させて
残念ながら Cに関しての書籍・サイトともに知りません。
が、http://alfin.mine.utsunomiya-u.ac.jp/~niy/algo/index.html で集められた関数等は勉強になると思います。
お礼コメント
panicdj

お礼率 22% (18/79)

yatokesaさん、何度もアドバイスありがとうございます。

>> C言語などを解説しているサイトでのサンプルコードとかでしょうか??
>も、含めてですね。オープンソースなプログラムとかでもよいと思います。勉強の種は沢山転がってますから探してみてください。

はい、承知しました。


yatokesaさん、いろいろ教えて頂きありがとうございました。
なお、本スレッドでお世話になった方にも感謝しています。
ありがとうございました!!
投稿日時 - 2001-08-29 19:10:14
-PR-
-PR-

その他の回答 (全8件)

  • 回答No.3
レベル12

ベストアンサー率 40% (201/496)

fuji1さんと同じ回答になってしまいました for (i = 0; i < X_MAX*Y_MAX*Z_MAX; i++) {  ↓ for (i = X_MAX*Y_MAX*Z_MAX; i; i--) { とした方が、多少スピードアップになると思います。 ...続きを読む
fuji1さんと同じ回答になってしまいました

for (i = 0; i < X_MAX*Y_MAX*Z_MAX; i++) {
 ↓
for (i = X_MAX*Y_MAX*Z_MAX; i; i--) {

とした方が、多少スピードアップになると思います。
補足コメント
panicdj

お礼率 22% (18/79)

すみません、なぜ以下のように、
for (i = X_MAX*Y_MAX*Z_MAX; i; i--) {
とすると、速くなるのでしょうか?
投稿日時 - 2001-08-28 18:59:16
  • 回答No.2
レベル12

ベストアンサー率 40% (201/496)

見やすさを優先するためのプログラミングをした方が良いと思いますよ。コンパイラの最適化によってあまり速度差がでないこともあります。 上限の決まっている領域の初期化は、for文かwhileを使うのは仕方ないことでしょう。それをふまえて、ポインタを使うと次のような感じで出きると思います。 int *p; int aa[X_MAX][Y_MAX][Z_MAX]; // 折角defineしているのだか ...続きを読む
見やすさを優先するためのプログラミングをした方が良いと思いますよ。コンパイラの最適化によってあまり速度差がでないこともあります。

上限の決まっている領域の初期化は、for文かwhileを使うのは仕方ないことでしょう。それをふまえて、ポインタを使うと次のような感じで出きると思います。

int *p;
int aa[X_MAX][Y_MAX][Z_MAX]; // 折角defineしているのだから、定数を使いましょう
int i;

p = (int*)aa;
for (i = 0; i < X_MAX*Y_MAX*Z_MAX; i++) {
 *p++ = 10; // 10.0は浮動小数です
}

ですか、ね。
お礼コメント
panicdj

お礼率 22% (18/79)

yatokesaさん、お返事ありがとうございます。

>見やすさを優先するためのプログラミングをした方が良いと思いますよ。
ごもっともですが、僕のプログラムはまだまだです。

細かい点も注意して頂きありがとうございます。

PS。yatokesaさんがプログラムを組む上で、または勉強した本やサイトの
中で推薦できるものがあったら教えて頂きたいのですが。。
僕は、一般的なC言語本にあるサンプルコードのような
レベルなのでなんとかその域から脱却したのですが。
投稿日時 - 2001-08-28 18:52:14
  • 回答No.1
レベル11

ベストアンサー率 29% (109/371)

こんにちは。 int 型なのに、10.0 入れてはいけませんよ。(^o^)丿 さて、配列の場合は、基本的にはリニアにメモリを確保されることになります。 ですから、 #define X_MAX 10 #define Y_MAX 20 #define Z_MAX 5 int main(int argc , char ** argv) { int i; int aa[ ...続きを読む
こんにちは。
int 型なのに、10.0 入れてはいけませんよ。(^o^)丿

さて、配列の場合は、基本的にはリニアにメモリを確保されることになります。
ですから、

#define X_MAX 10
#define Y_MAX 20
#define Z_MAX 5

int main(int argc , char ** argv)
{
int i;
int aa[10][20][5];
int *p ;

p = (int *)aa ;
for (i = 0; i < X_MAX * Y_MAX * Z_MAX; i ++) {
*(p++) = 10 ;
}

return 0;
}

でOKだと思います。

ただ、このリニアにとられるというのは、どんなときにもとは行かないので、アーキテクチャを確認する必要はありますね。

Wintel 系だったら大丈夫だと思いますが。
お礼コメント
panicdj

お礼率 22% (18/79)

fuji1さん早速の解答ありがとうございます。

御返答の内容について質問があります。
>配列は、基本的にはリニアにメモリを確保されることになります。
つまり、malloc()関数を用いたときと
異なり、連続的にメモリが確保されるというこですね?

>ただ、このリニアにとられるというのは、どんなときにもとは行かないので、
>アーキテクチャを確認する必要はありますね。

↑のことがよくわかりません。
リニアに確保できないarchitectureとは例えばどのような
構造でしょうか?
よろしければついでに教えて頂きたいのですが・・・


>Wintel 系だったら大丈夫だと思いますが。
Pentium 3を使っています.
投稿日時 - 2001-08-28 18:47:38
  • 回答No.4
レベル14

ベストアンサー率 50% (1122/2211)

No.2 の回答にある >「見やすさを優先するためのプログラミングをした方が良いと思います。」 に大きく同意しつつ、もうちょっと早そうなコードを。 int aa[X_MAX][Y_MAX][Z_MAX]; int* p = &aa[0][0][0]; int* p_end = &aa[X_MAX][Y_MAX][Z_MAX]; while (p != p_ ...続きを読む
No.2 の回答にある

>「見やすさを優先するためのプログラミングをした方が良いと思います。」

に大きく同意しつつ、もうちょっと早そうなコードを。

int aa[X_MAX][Y_MAX][Z_MAX];
int* p = &aa[0][0][0];
int* p_end = &aa[X_MAX][Y_MAX][Z_MAX];

while (p != p_end) {
  *p++ = 10;
}

もし、

int* p_end = &aa[X_MAX][Y_MAX][Z_MAX];

が気持ち悪いのであれば、

int* p_end = p + X_MAX * Y_MAX * Z_MAX;

でも OK 。

# この程度のサイズなら、たいした差は出ないと思いますよ。
お礼コメント
panicdj

お礼率 22% (18/79)

a-kumaさん、名前によらず天使のようなアドバイスありがとうございます!

>int* p_end = &aa[X_MAX][Y_MAX][Z_MAX]; (1)

>が気持ち悪いのであれば、

>int* p_end = p + X_MAX * Y_MAX * Z_MAX; (2)

僕の場合、なぜか(1)の方の初期化の方がしっくりきてしまいました。
(2)のような初期化はたいへん参考になります。

どうもありがとうございました!
投稿日時 - 2001-08-28 18:56:19
  • 回答No.5
レベル9

ベストアンサー率 40% (43/105)

int aa[X_MAX][Y_MAX][Z_MAX]; int *p = (int *)aa + sizeof (aa) / sizeof (int); while (p != (int *)aa) *--p = 10; 怒られそうだ(笑) ...続きを読む
int aa[X_MAX][Y_MAX][Z_MAX];
int *p = (int *)aa + sizeof (aa) / sizeof (int);

while (p != (int *)aa)
*--p = 10;

怒られそうだ(笑)
お礼コメント
panicdj

お礼率 22% (18/79)

mkiiさん、ご助言ありがとうございます!!
投稿日時 - 2001-08-29 14:23:03
  • 回答No.7
レベル10

ベストアンサー率 66% (103/155)

#4 a-kuma様 int* p_end = &aa[X_MAX][Y_MAX][Z_MAX]; は int* p_end = &aa[X_MAX-1][Y_MAX-1][Z_MAX-1] + 1; が正しいのではないかと... (^^;;; ...続きを読む
#4 a-kuma様

int* p_end = &aa[X_MAX][Y_MAX][Z_MAX];

int* p_end = &aa[X_MAX-1][Y_MAX-1][Z_MAX-1] + 1;
が正しいのではないかと... (^^;;;
お礼コメント
panicdj

お礼率 22% (18/79)

syuyamakawaさん、ご助言ありがとうございましたっ!!
投稿日時 - 2001-08-29 14:22:27
  • 回答No.6
レベル13

ベストアンサー率 34% (574/1662)

ポインタを理解するなら意味がありますが、 高速化の為に・・なら、あまり意味がないですね。 まず、意味があるほどの差がでないか、変わらないですし、 読みづらいプログラムは悪です(^^; >for (i = X_MAX*Y_MAX*Z_MAX; i; i--) { >とすると、速くなるのでしょうか? アセンブラレベルの話になりますが、 CPUの命令は、ある値とある値が等し ...続きを読む
ポインタを理解するなら意味がありますが、
高速化の為に・・なら、あまり意味がないですね。

まず、意味があるほどの差がでないか、変わらないですし、
読みづらいプログラムは悪です(^^;


>for (i = X_MAX*Y_MAX*Z_MAX; i; i--) {
>とすると、速くなるのでしょうか?
アセンブラレベルの話になりますが、
CPUの命令は、ある値とある値が等しいかを比べる命令が無いか,
あってもある数値が0かどうかを調べる命令より実行速度がたいてい遅いからです。
(命令が無い場合は引き算をして、結果が0かどうかを調べるという、二つの命令を実行することになります)

ただ、コンパイルしてアセンブラになる時に
どんな命令になるかはわかりませんから、
必ずしも速いとは言い切れません。
現在のコンパイラは最適化といって、
こういう高速化のための小細工は勝手にやりますので。
お礼コメント
panicdj

お礼率 22% (18/79)

terra5さん、詳しい解説ありがとうございました.

「処理はコンパイラが最適化する」とのことですが、
処理の高速を考える際は,どのような観点から
コードを組めばよろしいのでしょうか??

よろしくおねがいします!!
投稿日時 - 2001-08-29 14:26:50
  • 回答No.8
レベル12

ベストアンサー率 40% (201/496)

>for (i = X_MAX*Y_MAX*Z_MAX; i; i--) { >とすると、速くなるのでしょうか? 理屈は #6:terra5さんのとおりです。また、terra5さんの仰るとおり、コンパイラが勝手に最適化する可能性もありますので、知っている人が見れば気分的に早いコードだ!って気分になれる程度の速さです^^;)。デバッグモードなどでアセンブラとの混合リストを見ると違いが分かる ...続きを読む
>for (i = X_MAX*Y_MAX*Z_MAX; i; i--) {
>とすると、速くなるのでしょうか?
理屈は #6:terra5さんのとおりです。また、terra5さんの仰るとおり、コンパイラが勝手に最適化する可能性もありますので、知っている人が見れば気分的に早いコードだ!って気分になれる程度の速さです^^;)。デバッグモードなどでアセンブラとの混合リストを見ると違いが分かるかもしれません。

>レベルなのでなんとかその域から脱却したのですが。
私が Cを始めたのはもう十ン年前なので...。私が学習したのは「はじめてのC」というやつですがね。公開されている色々な人のコードを見るのが良い勉強になると思います。
ポインタを理解したいのなら、常に変数がどのメモリ(スタックも含めて)に配置されているのかを考えながらコーディングすることです。
お礼コメント
panicdj

お礼率 22% (18/79)

yatokesaさん,何度もアドバイスいただきありがとうございます。

>公開されている色々な人のコードを見るのが良い勉強になると思います

ちょっと、別件なのですが、↑は,サイトで公開されているコードとは、
C言語などを解説しているサイトでのサンプルコードとかでしょうか??

>ポインタを理解したいのなら、常に変数がどのメモリ(スタックも含めて)に配置されているのかを考えながらコーディングすることです。

上記についてもう少し教えてください.
これは、たとえばVCを用いているのであれば、デバッカの
混合モードを開いてアセンブラでどの変数がpushされているか
とか確認することなのでしょうか??

私は、詳しく混合モードの使い方
(例えば、espレジスタなどのレジスタの詳しい機能 他)
がよくわかっていません。

できることなら、参考になる書籍やサイトを提示させて
頂けると助かるのですが.

以上、どうかよろしくおねがいします!
投稿日時 - 2001-08-29 14:21:08
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ