• ベストアンサー

プログラミングテクニックについて(C言語).

terra5の回答

  • ベストアンサー
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.5

>この適材適所ともいうべき能力を身につけるには, >やはり「経験」でしょうか? アルゴリズム的なところは、計算量の問題ですから、 きちんと理詰めでいけば計算できるとは思いますし、 知識でもカバーできるとは思いますが。 何度もやっていれば、いちいち調べないでも すぐに頭に浮かぶのが経験ですしょうか。 >大きいサイズの場合,グローバル変数として確保した方がよい >ときいたことがあるのですが,これもなんともいえませんか? 言えないと思います。 おそらくスタック上に取られるauto変数だと、スタックサイズの制限により、 あまりに大きなエリアは取れれない可能性はありますが。 その場合でも、メモリをグローバルにするか、malloc()を使うか、また、場合によっては共有メモリを使うかとか、 場合によると思います。 もっとも、高速化より目的にあった・・の意味合いが強いとは思います。 >実際,関数を呼ぶときには,その呼ばれた関数内の変数も呼ばれる, >すなわち,スタックの繰り返しですよね? >ということは,あまり大きいサイズをつまないようにした方が >いいと知識がない私は考えてしまうのですが… 初期化が必要がない変数なら,まとめて取れますから、 速度的には数は影響しないでしょう。 また、popも関数の戻りにスタックポインタを復元すれば いいだけですから、通常は一命令でしょう。 たとえば、 f() { int a,b,c,d,e; ... } g() { int a; ... } では、手間は同一です。 って、実際はコンパイラ、CPUによるんでしょうが。 関数呼び出しの場合だと,手間がかかるのは 呼び出す前のレジスタの保存の方でしょう。 これはある程度,コンパイラの生成するコードと、 それを実行するCPUのアセンブラレベルの知識か、 それを調べることが必要でしょう。 ですが、やはりあまりすすめられないですね。 通常、それ以前の一般的な部分,アルゴリズムでの 高速化に及ばないですし。 処理の高速化は通常はアルゴリズムの改良です。 もし、処理にAPIやシステムコールが使われるなら, 重いAPIは極力使わないとかの工夫も含みます。 ところで、ダイアログの応答5秒とありますが、 本当に時間がかかる処理なら通常はマルチプロセスやマルチスレッドにすると思いますが。 ところで、配列をポインタにすることで高速化するという 話が出てますが, その程度のことは割と以前からコンパイラの最適化ではやっていると聞いてます。 最適化のレベルにもよると思いますが、Cコンパイラの最適化としてはかなり初歩的な部分でしょう。

noname#700
質問者

お礼

terra5 様,度重なるアドバイスありがとうございます. >その場合でも、メモリをグローバルにするか、malloc()を使うか、また、場合に >よっては共有メモリを使うかとか、 >場合によると思います。 >もっとも、高速化より目的にあった・・の意味合いが強いとは思います。 上記の意味は,リスト構造のような可変のデータをとりあつかうときは, malloc()を使うといったところでしょうか? しかし,「目的」に応じて,メモリーをグローバルにとる,または, 共有メモリにするといったアプローチは,私にとってちょっと 難しいところです.一例を指し示して頂けると分かりやすいのですが… >通常、それ以前の一般的な部分,アルゴリズムでの >高速化に及ばないですし。 >処理の高速化は通常はアルゴリズムの改良です。 アルゴリズムの改良ですか…うーーん,がんばって改良してみます. といっても,ここの関数の処理ルーチンについて再検討から始めたいと思います. >ところで、配列をポインタにすることで高速化するという >話が出てますが, >その程度のことは割と以前からコンパイラの最適化では >やっていると聞いてます。 >最適化のレベルにもよると思いますが、 >Cコンパイラの最適化としてはかなり初歩 >的な部分でしょう。 このようなコンパイラに関する知識も乏しいので,勉強ですね. terra5様はじめ,さまざまな方から意見を賜り,息詰まっていたキモチに モチベーションが戻りました.ここで改めてお礼を述べたいと思います. 有り難う御座いました.なにかまた不明瞭な点があったらこの掲示板を 利用させて頂くのでそのときは,どうか宜しく御願い致します. では.

関連するQ&A

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

    はじめまして。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文による繰り返す処理ではなく, その「ポインタ型によるアクセス」を実装したいのです。 こんな私にアドバイスお願い致します。

  • C言語の問題について

    下のプログラムにおいて実行結果は 02134 になります。 この02134になる過程は分かるのですが、時間がかかってしまいます。 iListとiGeneをいちいち紙に書き出さなければならないのでしょうか? 法則的なものが存在するとすれば、教えてください。 #include<stdio.h> #define MAX 5 void func(int *iGene); int main(void) { int i; int iGene[MAX]={0,1,0,0,0}; func(iGene); for(i=0;i<MAX;i++) { printf("%d",iGene[i]); } return (0); } void func(int *iGene) { int i,j; int iBuff; int iList[MAX]; for(i=0;i<MAX;i++) { iList[i]=i; } for(i=0;i<MAX;i++) { iBuff=iList[iGene[i]]; for(j=iGene[i]+1;j<MAX-i;j++) { iList[j-1]=iList[j]; } iGene[i]=iBuff; } } よろしくお願いします。

  • C言語 プログラミング 行列演算

    下記のプログラムのおかしい点と解決法を教えてください。 コンパイルは通りますがうまく動きません。。 #include<stdio.h> #define MAX 500 int main(void){ int matrA[MAX][MAX],matrB[MAX][MAX],matrC[MAX][MAX],l,m,n,i,j,k; printf("lとmを入力してください:"); scanf("%d",&l); scanf("%d",&m); printf("行列Aを入力してください"); for(i=0;i<l;i++){ printf(">"); for(j=0;l<m;j++){ scanf("%d",&matrA[i][j]); } printf("\n"); } printf("nを入力してください(m = %d):",m); scanf("%d",&n); printf("行列Bを入力してください"); for(i=0;i<m;i++){ printf(">"); for(j=0;j<n;j++){ scanf("%d",&matrB[i][j]); } printf("\n"); } printf("C=\n"); for(i=0;i<l;i++){ for(j=0;j<n;j++){ for(k=0;k<m;k++){ matrC[i][j]+=matrA[i][k]*matrB[k][j]; } printf("%d",matrC[i][j]); } printf("\n"); } }

  • C言語のプログラムについて。

    C言語のプログラミングについて質問です。 入力されたデータの配列とデータ数を渡すと配列に格納された値を逆順にして、格納し直す関数reverse関数を書き結果を出力せよ、というものなのですが下のように書いたのですが、うまく作動しません。どこがいけないのでしょうか...?教えていただきたいです。 #include <stdio.h> void reverse(int *data[], int n); #define MAX 100 int main() { int data[MAX]; int n, i; scanf("%d", &n); if (n >= MAX) n = MAX; for (i = 0; i < n; i ++){ scanf("%d", &data[i]); } reverse(data, n); for (i = 0; i < n; i ++) { printf("%d\n", data[i]); } return 0; } void reverse(int *data[], int n) { int c, i; for (i = 0; i < n; i ++) { c = *data[i]; *data[i] = *data[n - (i + 1)]; *data[n - (i + 1)] = c; } }

  • プログラミング(C言語)についての質問です

    3つの整数の入力を受け付け、最大と最小を求める関数を作成し得られた結果を表示するプログラミングを作成したつもりなのですが、うまく作動しません。(コンパイルはできますが、結果が無茶苦茶になります。) ご教授宜しくお願いします。 それと、課題文にはポインタを使って最大値と最小値を同時に求めるようにと書いてあったのですが、それもよくわからないです。 今回初めてポインタと配列の受け渡しについて習ったのでよくわかっていない部分も多いと思うのですが、何卒宜しくお願いします。 ちなみに関数の形自体は void minmax(int data[],int *min,int *max){} で決まっています。 #include <stdio.h> void minmax(int data[],int *min,int *max){ int i; *min=*max=data[0]; printf("1st intenger:"); scanf("%d",&data[0]); printf("2st intenger:"); scanf("%d",&data[1]); printf("3st intenger:"); scanf("%d",&data[2]); for(i=1;i<3;i++){ if(*max<data[i]){ *max=data[i]; } if(*min>data[i]){ *min=data[i]; } } } int main(void){ int data[3],min,max; minmax(data,&min,&max); printf("最小値は%dで最大値は%dです",min,max); return 0; }

  • C言語をお願いします

    何が違うのか教えてください。 segmentation faultになります。 よく分からないので、プログラムを作っていただければ、助かります。 問 整数を入力し、降順並び変えてに表示。 ・入力した整数は配列に入れ、その配列を使って並び変える(入力終りの印は 1000 とする)。 ・入力する整数の個数は #define NUM 100 を使いなさい。 ・使うデータは、下記の例のように、キーボードから入力すること。 #include<stdio.h> #define NUM 100 int main(void){ int d[NUM]; int temp; int i,j,n; printf("Input scores.\n"); for(i=0; i<NUM && d[i]!=1000; i++){ scanf("%d",&d[i]); } n = i; for(i = 0; i < n; i++){ for(j = i + 1; j < n;j++){ if(d[j] > d[i]){ temp = d[i]; d[j] = d[i]; d[i] = temp; } } } printf("After sort."); for(i=0; i < n; i++){ printf("%d\n",d[i]); } return 0; } 実行例 Input scores. 60 30 45 90 100 0 1000 After sort. 100 90 60 45 30 0 よろしければ 問2 並び変えをする部分を mysort 関数にしたプログラムを作ってください。 main 関数から mysort 関数には点数の個数と sort 前の配列を渡し、並び変え結果の表示はmain 関数でお願いします。 (問題の意味が分かりません) 関数はさっぱり分かりません。 では、お願い致します。

  • C言語の実行について、

    #include <stdio.h> #define N 2 void main(void) { int i ,j ; for( i=1 ; i <= N ; ++i) { for( j=i ; j < N+2 ; ++j) { printf("j=%d\n",j); } printf("i=%d\n",i); } } を実行すると、 j=1,j=2,j=3,i=1,j=2,j=3,i=2となったんですが、 どういった順序で行われているのでしょうか? よろしくお願いします。

  • シェルソート(Cプログラミング)

    シェル・ソート 基本挿入法により、データを昇順にソートする。 というプログラムを実行したいと思ったのですが、エラーがでてしまいコンパイルできません。 書いたプログラムは以下の通りです。 #include<stdio.h> #include<math.h> #define N 100 int main (void) { int a[N],i,j,t; for (i=0;i<N;i++) a[i]=rand(); for (i=1;i<N;i++){ for (j=j-1;j>=0;j--){ if (a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; } else break; } } for (i=0;i<N;i++) printf("%8d",a[i]); } エラーメッセージは以下のようにでました。 警告 W8065 sample.c 10: プロトタイプ宣言のない関数 'rand' の呼び出し(関数 main ) 警告 W8070 sample.c 22: 関数は値を返すべき(関数 main ) どうすれば出来るのでしょうか、お答えよろしくお願いします。

  • Cの素人がやってしまう・・・と言われた使い方

    関数set()を作って、下にコメントアウトされているプログラム と全く同じ動作をするプログラムを完成させよ。 main内部を変更してはならない。 関数set()内では鈎括弧を使用してはならない。 という問題で、終わるときにチェックされたのですが どうもsetでの中身が素人がよくやるやつ、といわれました。 int x[MAX]とやれ?ということなのでしょうか それともやはり&(*(x+i))の部分がおかしいということでしょうか? 確かにアドレスにアドレスを聞いているような理解としか、今は言いようがないのですが そいえば前回&*を使ってる人がいるけど・・・という話を聞きました 何かご指摘あればうれしいです 以下がコードになります。 #include <stdio.h> #define MAX 10 void set(int *x); int main() { int x[MAX]; int j; set(x); printf("KEKKA\n"); for (j = 0; j < MAX; ++j) { printf("%d\n", x[j]); } return 0; } void set(int *x) { int i; for(i = 0; i < MAX; ++i){ scanf("%d",&(*(x+i))); } } /* int main() { int x[MAX]; int j; for (j = 0; j < MAX; ++j) { scanf("%d", &x[j]); } printf("KEKKA\n"); for (j = 0; j < MAX; ++j) { printf("%d\n", x[j]); } return 0; } */

  • 【C言語】関数へのポインタ渡し

    配列中の最大値を発見するプログラムとして, 下記のようなプロブラムが参考書にのっていましたが,よくわからない箇所があり,質問させてください。 findMaxという関数に渡されているのは,aryの先頭アドレスだと思いますが, findMax関数内では,pary[]を引数としていますが,これはどういう意味なのでしょうか? 実際にどのような処理が行われているのかよくわかりません。 ポインタ変数? でもそのあとにはpary[0],pary[1]として使っているしよくわかりません。 教えていただけると嬉しいです。宜しくお願いいたします。 最近Cを学び始めましたが,ポインタがまだなれません…。 ============================ #include <stdio.h> #define DATA_SIZE (12) int ary[] = {5,7,10,1,25,15,30,10,31,13,22,32}; int findMax(int *, int); int main(void) { int max; int i; max = findMax(ary,DATA_SIZE); printf("Maximum number is %d\n",max); return(0); } int findMax(int pary[],int size){     int max;       int i; max = pary[0]; for(i = 0; i < size; i++){ if(pary[i] > max){ max = pary[i]; } } return(max); }