私はそれを何年も使用しています、すなわち:
text = (char *)malloc( sizeof(char[1234]) );
それ以外の:
text = (char *)malloc( sizeof(char) * 1234 );
危険だと言われましたが、理由は誰にも言えません。C仕様を確認しましたが、合法です。ここに落とし穴はありますか?
それは合法かもしれませんが、いくつかの落とし穴があります。
まず、あなた(または後のメンテナ)がやみくもに型を式に置き換えると、問題が発生します。
sizeof(char *) * 4 => sizeof(x) * 4 // OK
sizeof(char *[4]) => sizeof(x[4]) // NOT OK
次に、すべてのコンパイラが可変長配列をサポートしているわけではありません。
sizeof(char *) * n // ALWAYS SUPPORTED
sizeof(char *[n]) // MAY NOT BE SUPPORTED
最後に、これはあまり一般的なイディオムではないため、コードを読んでいる人は一時的に混乱する可能性があります。
もちろん、これらの落とし穴があなたの習慣を変える努力に値するかどうかはあなた次第です:)
私が使用するイディオムは次のとおりです。
someptr = malloc(number_elems * sizeof *someptr);
私にとって、これには、要素のタイプを変更する必要がある場合に、malloc呼び出しについて心配する必要がないという利点があります。
int *data;
data = malloc(100 * sizeof *data);
...後で私はデータがsであるべきだと気づきますunsigned long
...
unsigned long *data;
data = malloc(100 * sizeof *data); /* no change from previous version */
タイプの代わりに変数を使用することをお勧めします。
text = malloc(sizeof(*text)*1234));
このようにして、i18nをサポートするのが適切であることに気付いたときに、定義を次の
char *text;
よう
wchar_t *text;
に変更します。一致する「char」から「wchar_t」まで。もちろん、同じことが他のタイプにも当てはまります-short対int対long、float対doubleなど。
それは合法であり、あなたが言ったようにそれを行うのは安全です:
text = (char *)malloc( sizeof(char[1234]) );
通常、人々は、カウントにパディングを含めて乗り越えるために、最も最小のプリミティブデータ型でsizeofを使用します。
配列に要素の間にパディングがある可能性があると誰かが考えていたため、安全ではないと聞いたことがあるでしょう。
ただし、配列の要素の間にパディングが存在することはありません。C99標準では、配列はメモリの連続部分でなければならないと規定されています。
Cの構造体内でも、配列の前または後にパディングを行うことができます。
2つの間に実際的な違いがあります。最初のバージョンでは、オブジェクトの数はコンパイル時定数である必要があります。2番目のバージョンでは、要素の数を実行時に決定できます。
だから、両方が
size_t x = sizeof(double[99]);
size_t y = sizeof(double)*99;
期待どおりに機能しますが、次の例では機能しません
void fun(int i) {
size_t x = sizeof(double[i]); // error, no compile-time constant
size_t y = sizeof(double) * i; // Fine
}