4

私はCの専門家ではありませんが、これが私がやろうとしていることです。

int main(void) {
    double *myArray;
    ...
    myFunction(myArray);
    ...
    /* save myArray contents to file */
    ...
    free(myArray);
    ...
    return 0;
}

int myFunction(double *myArray) {
    int len=0;
    ...
    /* compute len */
    ...
    myArray = malloc( sizeof(double) * len );
    if (myArray == NULL) 
      exit(1);
    ...
    /* populate myArray */
    ...
    return 0;
}

myArray内部の内容を保存したいのmainですが、プログラムが内部になるまで必要なサイズがわかりませんmyFunction

CentOS 6.2 Linuxを使用しているので、4.4.6までのgccビルドしか見つかりませんでした(可変長配列を宣言するC99機能をサポートしていません。「可変長配列の「壊れた」」を参照してください。http://gcc.gnu.org/gcc-4.4/c99status.html-std=c89 )、コンパイルに使用してスタックしています。

4

4 に答える 4

3

簡単な答えはノーです。

ポインタを返していません。

使用する

int main(void) {
    double *myArray;
    ...
    myFunction(&myArray);
    ...
    /* save myArray contents to file */
    ...
    free(myArray);
    ...
    return 0;
}

int myFunction(double **myArray) {
    int len=0;
    ...
    /* compute len */
    ...
    *myArray = malloc( sizeof(double) * len );
    if (NULL == *myArray) 
      exit(1);
    ...

編集

    poputateThis = *myArray;

    /* populate poputateThis */

編集終了

    ...
    return 0;

編集

あなたの}のために泥棒を単純化する必要があります

于 2012-11-19T18:45:08.303 に答える
2

mainに保持されmyFunctionている値は変更されないため、実行していることはOKではありません。myArray自分のコピーを変更するだけです。

それ以外は、スタイリスト的に議論の余地があっても大丈夫です。

于 2012-11-19T18:43:14.840 に答える
2

優れた設計と実践の問題として(他の回答で指摘されている構文の問題は別として)、コードベースのベストプラクティスと一致し、透過的である限り、これは問題ありません。関数を文書化して、呼び出し元が関数を解放する必要があることを認識し、さらに独自のメモリを割り当てないことを認識できるようにする必要があります。さらに、次のような抽象データ型を作成することを検討してください。

// myarray.h
   struct myarray_t;
   int myarray_init(myarray_t* array); //int for return code
   int myarray_cleanup(myarray_t* array); // will clean up

myarray_tinitcleanup関数ではそれぞれ割り当てと割り当て解除を行いますが、呼び出し元の関数からカプセル化される動的ポインタを保持します。

于 2012-11-19T18:47:50.787 に答える
1

あなたがしたいことは問題ありませんが、あなたのコードはそれをしません-main割り当てられたメモリを見ることは決してありません。のパラメータmyArraymyFunction、関数呼び出しで渡された値で初期化されますが、その後変更しても、内の同じ名前の無関係な変数は変更されませんmain

myFunctionこれは、常にを返すコードスニペットに表示されます0。もしそうなら、あなたのコードを修正する最も明白な方法は、代わりに戻ることですmyArray(そしてパラメータを取りません)。その場合、呼び出しは次のようにmainなりますmyArray = myFunction();

myFunction実際にすでにその戻り値を使用している場合は、へのポインターを渡しdouble*、そのポインターの参照にアドレスを書き込むことができます。これがEdHealの答えです。このdouble **パラメーターは、関数が出力を格納するために使用する場所へのポインターであるため、「out-param」と呼ばれることがよくあります。この場合、出力はバッファのアドレスです。

別の方法は、次のようなことを行うことです。

size_t myFunction(double *myArray, size_t buf_len) {
    int len=0;
    ...
    /* compute len */
    ...
    if (buf_len < len) {
        return len;
    }
    /* populate myArray */
    ...
    return len;
}

そうすれば、発信者は好きなようにメモリを割り当てることができます。一般的な呼び出しコードは次のようになります。

size_t len = myFunction(NULL, 0);
// warning -- watch the case where len == 0, if that is possible
double *myArray = malloc(len * sizeof(*myArray));
if (!myArray) exit(1);
myFunction(myArray, len);
...
free(myArray);

あなたが得たのは、発信者が便利な場所からメモリを割り当てることができるということです。あなたが失ったのは、発信者がより多くのコードを書かなければならないということです。

その自由を使用する方法の例として、発信者は次のように書くことができます。

#define SMALLSIZE 10;

void one_of_several_jobs() {
    // doesn't usually require much space, occasionally does
    double smallbuf[SMALLSIZE];
    double *buf = 0;

    size_t len = myFunction(smallbuf, SMALLSIZE);
    if (len > SMALLSIZE) {
        double *buf = malloc(len * sizeof(*buf));
        if (!buf) {
            puts("this job is too big, skipping it and moving to the next one");
            return;
        }
    } else {
        buf = smallbuf;
    }

    // use buf and len for something
    ...

    if (buf != smallbuf) free(buf);
}

malloc小さなバッファのみが必要な一般的なケースでは、これを回避することは通常不要な最適化です。これは、呼び出し元がメモリの割り当て方法について発言したい理由の一例にすぎません。より差し迫った理由は、おそらく別のコンパイラを使用して、関数が呼び出し元の関数とは異なるdllにコンパイルされ、2つが互換性のあるの実装を使用していないことである可能性がありmalloc/freeます。

于 2012-11-19T18:49:48.587 に答える