fread()
Cでファイルからメモリと配列データを割り当てる最も健全な方法は何だろうか.
まず、説明:
int32_t longBuffer;
ここで、longBuffer を freading すると、コードは次のようになります。
fread(&longBuffer, sizeof(longBuffer), 1, fd); //version 1
fread(&longBuffer, sizeof(int32_t), 1, fd); //version 2
2 つのうち、バージョン 1 はよりバグセーフであると言えます。なぜなら、 の型がlongBuffer
変更された場合 (たとえば に)、を新しい型で更新するのint16_t
を忘れることを心配する必要がないからです。fread()
sizeof()
ここで、データの配列の場合、コードは次のように記述できます。
//listing 1
int8_t *charpBuffer=NULL; //line 1
charpBuffer = calloc(len, sizeof(int8_t)); //line 2
fread(charpBuffer, sizeof(int8_t), len, fd); //line 3
sizeof(<type>)
ただし、これは最初の例で明らかになった問題を示しています。の型を変更するときに命令を同期することを忘れないように注意する必要がありcharpBuffer
ます (たとえば、 からint8_t*
へint16_t*
)。
したがって、次のように書こうとするかもしれません。
fread(charpBuffer, sizeof(charpBuffer[0]), len, fd); //line 3a
よりバグセーフなバージョンとして。2行目の割り当ての後、書き込みcharpBuffer[0]
は完全に有効になるため、これは機能するはずです。
また、次のように書くこともできます。
fread(charpBuffer, sizeof(*charpBuffer), len, fd); //line 3b
ただし、次のようなメモリ割り当てに対して同じことを試みます。
charpBuffer = calloc(len, sizeof(charpBuffer[0])); //line 2a
構文は優れていますが、未定義の動作を示します。これは、この段階でcharpBuffer[0]
結果を書き込むと、NULL ポインターが逆参照されるためです。また、次のように書いています。
charpBuffer = calloc(len, sizeof(*charpBuffer)); //line 2b
は同じ問題を示します。
だから、今の質問:
コードの「2b行目」と「3b行目」は正しいですか(この質問の未定義の動作は無視してください)、または「2a行目/3a行目」や「2行目」 /3"?
「リスト 1」のコードを記述し、未定義の動作を回避する最もバグの少ない方法は何でしょうか?
編集(いくつかの側面を明確にするため):
議論は間違った方向に進みました。コンパイル時間と実行時間の問題は 1 つの問題です (これについても標準的な保証が必要ですが、それはトピックではありません)。また、 sizeof(NULL dereferencing) の未定義の動作の問題は別のものです。コンパイル時であっても、これが標準によってUBにならないように保証されているとは確信していません。規格は何らかの保証を提供していますか?