2011-01-31 9 views
2

私はちょうどCを学び始めました(C#の背景から来ています)。最初のプログラムでは、要素を計算するプログラムを作成することにしました。関数にポインタを渡してから、対応する変数を更新する必要があります。初心者の質問です。ポインターをCの関数に渡すには?

findFactors関数の宣言時にポインタを引数として渡したいと表示していないため、「findFactorsの型が競合しています」というエラーが表示されます。どんな助けでも大歓迎です!

#include <stdio.h> 
#include <stdlib.h> 

int *findFactors(int, int); 

int main (int argc, const char * argv[]) 
{ 
    int numToFind; 

do { 
    printf("Enter a number to find the factors of: "); 
    scanf("%d", &numToFind);  
} while (numToFind > 100); 

    int factorCount; 
findFactors(numToFind, &factorCount); 

return 0; 
} 

int *findFactors(int input, int *numberOfFactors) 
{ 
int *results = malloc(input); 
int count = 0; 
for (int counter = 2; counter < input; counter++) { 
    if (input % counter == 0){ 
     results[count] = counter; 
     count++; 
     printf("%d is factor number %d\n", counter, count); 
    } 
} 

return results; 
} 
+0

それを実演しました。 int **そしてint ** numberOfFactors – JoeS88

答えて

3

変更の定義と一致するように宣言:

int *findFactors(int, int *); 
0
int* ip <- pointer to a an int 
int** ipp <- pointer to a pointer to an int. 
+0

助けをいただきありがとうございます。 – JoeS88

1

EDIT:Cで無参照(C++機能)

は方法でnumberOfFactorsを変更することを忘れないでください(有用でない場合はこのパラメータを削除してください)。ファイルの先頭のシグネチャも、最後に実装のシグネチャと一致する必要があります(これがエラーです)。

最後に、結果のmallocが正しくありません。あなたはこれを実行する必要があります。

int *results = malloc(input * sizeof(int)); 
+1

参照はCには存在しません。彼らはC + +の機能です。 –

0

int *findFactors(int, int);ラインは、あなたがこの関数からポインタを返すたいと言う(それは近いタイプ名にasteriksを使用することをお勧めします:int* moo(); - これは誤解私は考えるのを防止します)。

あなたが動的に(単なるポインタを返すよりも良い方法です)関数の引数を変更したい場合は、すでにこの変数を持っているかのように、あなただけの引数を使用する必要があります。

そして最後に、あなたの間違い:malloc(X)Xバイトを割り当てますので、あなたは、いくつかの配列にメモリを割り当てたい場合、あなたはNがあなたの配列のサイズであるとTはそのタイプであるmalloc(N * sizeof(T));を、使用する必要があります。例:int *aが必要な場合は、int *a = (int*) malloc(10 * sizeof(int));とする必要があります。

そして今ここに固定あなたのコードは、(私にとってのように)です:

#include <stdio.h> 
#include <stdlib.h> 

int findFactors(int, int*); 

int main(int argc, char **argv) 
{ 
    int numToFind, *factors = 0, cnt = 0; 

    do 
    { 
    printf("Enter a number to find the factors of: "); 
    scanf("%d", &numToFind);  
    } while (numToFind > 100); 

    cnt = findFactors(numToFind, factors); 

    printf("%d has %d factors.\n", numToFind, cnt); 

    return 0; 
} 

int findFactors(int N, int* factors) 
{ 
    if (!factors) 
    factors = (int*) malloc(N * sizeof(int)); 

    int count = 0; 

    for (int i = 2; i < N; i++) 
    { 
    if (N % i == 0) 
    { 
     factors[count++] = i; 
     printf("%d is factor number #%d\n", i, count); 
    } 
    } 

    return count; 
} 

注:(私が行ったように)があなたのポインタの任意の時間を初期化することを忘れないでください。関数を呼び出し、その引数としてポインタを渡したい場合は、少なくとも関数呼び出しの前に値が0であることを確認する必要があります。そうしないと、実行時エラーが発生します。

+0

'malloc'によって返されたメモリがゼロで初期化されていません。あなたは 'memset(factors、0、sizeof(int)* N);を加えなければなりません;そうでなければ値は未定義です。 –

2

私はまだ別の答えを追加することをお詫びしますが、私は誰もあなたの質問でカバーする必要があるすべてのポイントをカバーしていないと思います。

1)malloc()を使用してメモリを動的に割り当てるときは、いつでも終了したらfree()にする必要があります。オペレーティングシステムは、通常、あなたの後にきちんと整理されますが、いくつかのメモリを使用する実行可能ファイルの中にプロセスがあることを考慮してください。上記のプロセスが完了すると、そのメモリがfree()の場合、プロセスに使用可能なメモリが増えます。それは効率性についてです。

int* somememory = malloc(sizeyouwant * sizeof(int)); 
// do something 
free(somememory); 

簡単:無料正しくを使用するには

2)mallocを使用するたびに、実際の割り当てはバイト単位であるため、malloc(numofelements*sizeof(type));を実行する必要があります。あまり広く使われていないcallocという機能があり、これはおそらく理解しやすいcalloc(num, sizeof(type));のようなものです。 callocもメモリを0に初期化します

3)あなたはmallocの戻り値の型をキャストする必要はありません。私はプログラミングの本がたくさんあることを示唆しています.C++では必須であることを義務づけています(ただし、C++ではnew/deleteを使用する必要があります)。 this questionを参照してください。

4)あなたの関数のシグネチャは確かに間違っていた - 関数のシグネチャは、その機能と一致する必要があります。

5)関数からポインタを返すには、それは私が落胆ものですが、それはそれ自体は間違っていないです。言及する2つのポイント:常に1)を念頭に置いてください。私はaskedとまったく同じ問題を抱えており、基本的にはこれらの呼び出しを追跡することになります。より高度なユーザーとして、気にするアロケータタイプもあります。

ここでもう一つのポイントは、この関数を考えてみます。

int* badfunction() 
{ 
    int x = 42; 
    int *y = &x; 
    return y; 
} 

これは悪い、悪い、悪いです。ここでは、badfunctionの場合に限り、xへのポインタを作成して返します。戻り時に、が存在しなくなる変数へのアドレスがあります。通常、スタックにはxが作成されるためです。時間の経過とともにそれについてもっと学びます。今のところ、変数がその機能を超えて存在しないと思うだけです。

int* y = malloc(...は、mallocのためにメモリがヒープ上に作成され、したがってその関数の終わりに耐えないことに注意してください。

私は関数のシグネチャとして何を勧めますか?私の変更は単なる個人的な好みです

int findFactors(int* factors, const int N); 

:私は実際にはわずかな修正でshybovychaの機能となるだろう。私はconstを使用するので、何かが関数の入力の一部であることがわかります。厳密にはintでは必要ではありませんが、ポインタを渡している場合は、先にconstを使用しない限り、ソースメモリを変更できることを覚えておいてください。だから、この場合はちょうど習慣です。

第二の変化は、私はいつもそのように周りだと思うので、私はすなわちoutput = func(input)、左側の出力パラメータを好むということです。

ポインタを使用する場合は、なぜあなたは、関数の引数を変更することができますか?変数へのポインタを渡したからです。これはちょうどメモリアドレスです - 私たちがそれを "逆参照"すると(そのアドレスの値にアクセスする)、それを変更することができます。技術的に言えば、Cは厳密に値渡しです。ポインタはそれ自身がメモリアドレスを含む変数であり、これらの変数の内容は関数にコピーされます。したがって、通常の変数(たとえばint)は、渡されたもののコピーに過ぎません。int* factorsは、渡したポインタ変数のアドレスのコピーです。設計上、元のコピーとこのコピーが同じメモリを指しているので、参照を外すと、呼び出し元と元の関数の両方でそのメモリを編集できます。

私はいくつかをクリアすることを願っています。

+0

+はfree()に言及しています。オリジナルのポスターはC#プログラマなので、手動でメモリをクリーンアップするのは難しいでしょう。それらはガベージコレクションに使用されます。 – Lundin

+0

8年のリアルタイムシステム開発者からの+1は非常に褒め言葉です。ありがとう。私は他の誰もそれを見つけたり、言及に値するとは思わなかった。 –