2

私がC関数を持っているとしましょう:

void myFunction(..., int nObs){
    int myVec[nObs] ;
    ...
}

myVecは動的に割り当てられていますか?myFunctionが呼び出されるたびに、nObsは一定ではありません。私は現在この習慣でプログラミングを行っているので、友人が彼のプログラムでエラーを抱えていたので、彼は配列を動的に割り当てなかったことが原因であると尋ねます。私のプログラミングの習慣(上記の例のように初期化する)が安全な習慣であるかどうかを知りたいです。

ありがとう。

4

3 に答える 3

3

あなたの質問に答えるために、それはスタックにあるので動的割り当てとは見なされません。これが許可される前は、一部のプラットフォームでは、関数を使用してスタック上の同じ可変長割り当てをシミュレートできましたallocaが、それは移植性がありませんでした。これは(C99用にプログラムする場合)です。

于 2010-02-23T05:59:04.917 に答える
1

コンパイラに依存します。gccで問題ないことはわかっていますが、C89仕様では許可されていないと思います。C99のような新しいC仕様についてはよくわかりません。移植性のための最善の策は、それを使用しないことです。

于 2010-02-23T05:53:01.990 に答える
1

これは「可変長配列」として知られています。サイズは実行時に決定され、呼び出しごとに変更できるという意味で動的ですが、auto他のローカル変数と同様にストレージクラスがあります。混乱を招くだけなので、これに「動的割り当て」という用語を使用することは避けたいと思います。

「動的割り当て」という用語は通常、ヒープから割り当てられ、その存続期間がオブジェクトのスコープではなくプログラマーによって(new / delete、malloc / freeによって)決定されるメモリおよびオブジェクトに使用されます。auto可変長配列は、ストレージクラスを持つ他のローカル変数と同様に、スコープに出入りするときに自動的に割り当てられ、破棄されます。

可変長配列は、コンパイラーによって普遍的にサポートされていません。特にVC++はC99(したがって可変長配列)をサポートしておらず、サポートする予定はありません。現在、C++もそれらをサポートしていません。

それが「安全な習慣」であることに関しては、移植性の問題は別として、スタックがオーバーフローする可能性があることは明らかでありnObs、値を十分に大きくする必要があります。nObsたとえば、より小さい整数型を作成するuint8_tことでこれをある程度防ぐことができますがuint16_t、これはあまり柔軟なソリューションではなく、スタックのサイズと割り当てられるオブジェクトについて大胆な仮定をします。が推奨されるassert(nObs < MAX_OBS)場合もありますが、その時点でスタックがすでにオーバーフローしている可能性があります(ただし、assert()によって終了が発生するため、これで問題ない場合があります)。

[編集]サイズが例のように外部で決定されていない場合は、可変長配列を使用してもおそらく問題ありません。[/編集]

全体として、移植性とスタックの安全性の問題は、可変長アレイがIMOを回避するのが最善であることを示唆しています。

于 2010-02-23T15:21:36.310 に答える