freeの戻り値をvoidにキャストする理由


82

私はCを使用した本(Butenhofによるプログラミング、POSIXスレッドによるプログラミング、1997)を読んでいて、次の行に出くわしました。

(void)free(data);

ここでdataは、割り当てられた構造体への単なるポインタですが、

data = malloc(sizeof(my_struct_t));

freeキャストされた結果はなぜvoidですか?

Cについての私の理解から、これは2つの理由で意味をなさないようです:

  • 無料の関数はすでに戻ります void
  • コードは戻り値を使用していません(変数に割り当てられていません)

本は1997年に書かれました。これはある種のレガシーなものですか?

著者は、例がDigital Unix 4.0dで実行されたと述べていますが、その結果を使用しないのであれば、関数の結果をキャストする理由を想像することはできません。


いくつかの可能な説明はここで見つけることができます:stackoverflow.com/questions/689677/...
チンボ

3
好奇心から、あなたのC本の出版日はいつですか?(それはどの本ですか?)それが1995年以前である場合、それについて何らかの正当化があるかもしれません—標準のCコンパイラはその頃まで至る所にありませんでした。それがその後発行され、それでもキャストが含まれている場合(およびその理由の説明がない場合)、それがあなたに教えている他の悪い習慣について心配してください。最新の本を入手してください!
ジョナサンレフラー


3
@JonathanLefflerは、私の最初の投稿で述べたように、1997年に出版され、UNIX 4.0dを使用していました。この本は、David R. Butenhofによる「Programming with POSIX Threads」です。これまでのところ、それは非常に有益であり、POSIXスレッド標準への元の貢献者の1人によって書かれました。
アダムジョンストン

6
私は先週、そのコピーを使用していました—はい、それでもまだ役に立ちます。それは「ユビキタス標準C」(私は「1995年頃」と言った)の先端に書かれました。'UNIX 4.0d'はDigital UNIXのように聞こえます—ブテンホフが働いていたのはそのためです。キャストをfree()、エミュレートする必要のない本の奇妙なものとして扱います。昔は半関連性がありましたが、もう関連性はありません。
ジョナサンレフラー

回答:


100

標準free関数について話している場合、そのプロトタイプは

void free(void *ptr);

したがって、キャストは完全に無意味です。
今いくつかの推測。

作成者がstdlib.hこのプロトタイプを宣言するヘッダーを含めるのを忘れている可能性があるため、コンパイラーはその戻り型をと想定していintます。このコードの静的分析中に、コンパイラーは、void関数ではないと考えられるものの未使用の戻り値について警告していました。そのような警告は通常、キャストをに追加することで抑制されvoidます。


50
ただし、キャストが推測された理由で導入された場合、それを使用して警告を止めるのは正しくありません。その場合、コンパイラーはfree実際のタイプとは異なるタイプを原因とするため、呼び出しの動作は未定義になります(C90のセマンティクスで、宣言されていない関数を呼び出しても、すべてのケースでUBが本質的に発生するとは限りません)。実際には、一部のシステムで本当の不正な動作が発生する可能性があります。正しい解決策は、関数の正しい宣言を提供することです。
ジョンボリンジャー

11
特に、「POSIXスレッドを使用したプログラミング」の例では、関連する標準ヘッダーが繰り返し含まれていません。多分これは作者によるいくつかの悪い習慣でした、彼らはデフォルトですべての標準ライブラリを含む非標準のコンパイラ設定を使用している可能性があります。
ランディン

74

それは古いものでしょう!

C標準が存在する以前は、free()関数は(暗黙的に)intvoidでした。戻り値の型がまだ確実に存在していないためです。返される値はありませんでした。

標準のCコンパイラで動作するようにコードが最初に変更されたときは、おそらく含ま<stdlib.h>れていませんでした(標準の前には存在しなかったため)。古いコードは、割り当て関数(およびと同様)に対してextern char *malloc();(おそらくなしでextern)作成し、を宣言する必要はありませんでした。そして、コードは戻り値を正しい型にキャストします。これは、少なくとも一部のシステム(Cで学習したものを含む)では必要であったためです。calloc()realloc()free()

しばらくして(void)キャストが追加され、コンパイラー(または、より可能性が高いlint)に、「からの戻り値free()は意図的に無視される」ことを伝え、不満を回避しました。ただし、追加<stdlib.h>して、その宣言またはコンパイラに無視する値がないことをextern void free(void *vp);通知させる方が良いでしょうlint

JFTR:80年代半ばに戻ると、ICL Perqは元々はワード指向のアーキテクチャにあり、char *メモリロケーションのアドレスは、「anything_elseポインター」と同じロケーションへの非常に異なる番号でした。char *malloc()どういうわけか宣言することが重要でした。その結果を他のポインタ型にキャストすることが重要でした。キャストは実際にCPUが使用する数を変更しました。(システムのメインメモリが1 MiBから2 MiBにアップグレードされたときも大きな喜びでした。カーネルが約3/4 MiBを使用したため、ユーザープログラムがページングなどの前に1 1/4 MiBを使用できることを意味します。)


9
free()on pの実装を含むK&R、第1版のコピーを開いたところです。暗黙的に177を返しますint
ex nihilo

9
もちろん、— void標準がリリースされる前に一部のシステム(Unix System IIIなど)に追加されましたが、K&R 1st Ednが書かれたとき(1978)、Cの一部ではありませんでした。値を返さなかった関数は、戻り値の型なしで宣言されました(つまり、が返されましたint)。返されなかった値を使用しない限り、問題はありませんでした。C90標準は、そのようなコードを有効なものとして扱う必要がありました。標準がそうでなかったのと同じように、それは大げさに失敗したでしょう。しかし、C99は「暗黙的int」および「暗黙的関数宣言」ルールを削除しました。世界のすべてのコードが追いついているわけではありません。
ジョナサンレフラー

5
オペは本が1997年に書かれたと主張します。ここで話しているのはごく初期の先行標準「K&R C」であり、誰もそれについて本を書くことはほとんどありそうにありません。私の知る限り存在したそのような本は、確かにK&Rの最初の版でした。
ランディン

暗黙の宣言を回避できると思った場合、ヘッダーを含めないことは(おかしな場合は)頻繁に行われていました。ビルド時間を短縮すると考えられていたためです。
スペンサー

誰かが(void)キャストを使用していますかprintf()
ルイスコロラド

11

このキャストは必要ありません。CはC89の形式で標準化されていたため、おそらく当時はなかったでしょう。

もしそうなら、それは暗黙の宣言によるものでした。これは通常、コードを作成した人が忘れてい#include <stdlib.h>て、静的アナライザーが使用されていたことを意味します。これは最善の回避策ではなく、#include <stdlib.h>代わりにはるかに良いアイデアがあったでしょう。暗黙の宣言についてのC89からの言い回しは次のとおりです。

関数呼び出しで括弧で囲まれた引数リストの前にある式が識別子のみで構成されており、この識別子の宣言が表示されていない場合、その識別子は、関数呼び出しを含む最も内側のブロックで宣言とまったく同じように暗黙的に宣言されます。

extern int identifier();

登場した。

彼らは結果キャストしていないので、しかし、それは奇妙だmallocのいずれかを、そしてmallocfree同じヘッダファイルです。

また、これが単なる誤りであるかfree、結果を返さないことをリーダーに伝える何らかの方法である可能性もあります。


5
言語が標準化されたからといって、誰もがすぐにツールチェーンとコードを更新してそれに準拠するようになるわけではありません。古いスタイルの "K&R" Cがさらに8年間スタックしていたのはもっともなことです。それでも、静的分析ツールがのキャストを必要とするが、のキャストを必要としfreeないのは奇妙であることに同意しmallocます。
dan04

4
@ dan04あなたは通常mallocの結果を使用します;)(void)printf(...)多くのプロジェクトで発生します。
richardb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.