mallocの結果をキャストしますか?

2479
Patrick McDonald 2009-03-04 00:13.

大きな配列を宣言するときにスタックオーバーフロー例外を取得する、誰かがで提案されている大きな配列を宣言するときにスタックオーバーフロー例外を取得する、私がすべきことではないの結果キャストmallocすなわち、

int *sieve = malloc(sizeof(int) * length);

のではなく:

int *sieve = (int *) malloc(sizeof(int) * length);

なぜそうなるのでしょうか?

29 answers

2285
unwind 2009-03-04 00:17.

いいえ; 次の理由により、結果をキャストしません

  • void *この場合、他のポインタタイプに自動的かつ安全に昇格されるため、これは不要です。
  • コードが煩雑になり、キャストが読みにくくなります(特にポインターの種類が長い場合)。
  • それはあなたが自分自身を繰り返すようにします、それは一般的に悪いです。
  • を含めるのを忘れた場合、エラーを非表示にすることができます<stdlib.h>。これによりクラッシュが発生する可能性があります(さらに悪いことに、コードのまったく異なる部分で後でクラッシュが発生することはありません)。ポインタと整数のサイズが異なる場合はどうなるかを考えてください。次に、キャストによって警告を非表示にし、返されたアドレスの一部を失う可能性があります。注:C99以降、暗黙関数はCから削除され、宣言されていない関数がを返すという自動的な仮定がないため、この点は関係ありませんint

私は「あなたはキャストしていない」と述べたことを明確に、注意点としては、「あなたはしていないではない必要があるキャストに」。私の意見では、たとえあなたがそれを正しく理解したとしても、キャストを含めることは失敗です。それを行うことには何のメリットもありませんが、潜在的なリスクがたくさんあり、キャストを含めることは、リスクについて知らないことを示しています。

また、コメンテーターが指摘しているように、上記はC ++ではなく、ストレートCについて説明していることに注意してください。私はCとC ++を別々の言語として非常に固く信じています。

さらに追加するには、コードがタイプ情報(int)を不必要に繰り返すため、エラーが発生する可能性があります。戻り値を格納するために使用されているポインタを逆参照して、2つを一緒に「ロック」することをお勧めします。

int *sieve = malloc(length * sizeof *sieve);

これlengthにより、が前面に移動して視認性が向上し、冗長な括弧がsizeof;で削除されます。彼らは唯一必要な引数は型の名前であるとき。多くの人はこれを知らない(または無視する)ようで、コードがより冗長になります。覚えておいてください:sizeofは機能ではありません!:)


移動しながらlength前にするとまれでは視認性を高める、1はまた、一般的なケースでは、それはのように式を記述する方が良いでなければならないことに注意を払う必要があります。

int *sieve = malloc(sizeof *sieve * length);

sizeofこの場合、最初のものを保持するので、乗算が少なくともsize_t数学で行われることが保証されます。

比較:malloc(sizeof *sieve * length * width)malloc(length * width * sizeof *sieve)二はオーバーフローするlength * widthときwidthlength比べて小さいタイプですsize_t

387
dirkgently 2009-03-04 00:17.

Cでは、の戻り値をキャストする必要はありませんmalloc。によって返されるvoidへのポインタmallocは、自動的に正しい型に変換されます。ただし、コードをC ++コンパイラでコンパイルする場合は、キャストが必要です。コミュニティの中で好ましい代替手段は、以下を使用することです。

int *sieve = malloc(sizeof *sieve * length);

これにより、のタイプを変更した場合でも、式の右辺を変更する必要がなくなりますsieve

人々が指摘しているように、キャストは悪いです。特にポインターキャスト。

360
Ron Burk 2013-02-15 06:15.

あなたがないので、キャスト:

  • これにより、コードはCとC ++の間でより移植性高くなり、SOの経験が示すように、非常に多くのプログラマーが、実際にC ++(またはCとローカルコンパイラ拡張)で記述しているのにCで記述していると主張しています。
  • そうしないと、エラーが隠される可能性があります。いつ書き込むtype *かとを混乱させるSOの例をすべて注意してくださいtype **
  • #include適切なヘッダーファイルに失敗したことに気付かないようにするという考えは、ツリーのフォレストを見逃します。これは、「プロトタイプが表示されないことについてコンパイラに文句を言うように依頼しなかったという事実を心配しないでください。厄介なstdlib.hは覚えておくべき本当に重要なことです!」と言うのと同じです。
  • それは余分な認知クロスチェックを強制します。それはあなたがその変数の生のサイズのために行っている算術のすぐ隣に(主張されている)望ましいタイプを置きます。malloc()キャストがあるとバグがはるかに早くキャッ​​チされることを示すSO調査を行うことができると思います。アサーションと同様に、意図を明らかにするアノテーションはバグを減らします。
  • マシンがチェックできる方法で自分自身を繰り返すことは、多くの場合素晴らしいアイデアです。実際、それがアサーションであり、このキャストの使用はアサーションです。チューリングが何年も前にアイデアを思いついたので、アサーションはまだコードを正しくするために私たちが持っている最も一般的なテクニックです。
174
quinmars 2009-03-04 01:17.

他の人が述べたように、Cには必要ありませんが、C ++には必要です。何らかの理由でCコードをC ++コンパイラでコンパイルする場合は、代わりに次のようなマクロを使用できます。

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

そうすれば、非常にコンパクトな方法でそれを書くことができます。

int *sieve = NEW(int, 1);

そしてそれはCとC ++のためにコンパイルされます。

146
ashiquzzaman33 2015-10-10 11:23.

ウィキペディアから:

鋳造の利点

  • キャストを含めると、Cプログラムまたは関数をC ++としてコンパイルできる場合があります。

  • キャストにより、元々char *を返していた1989年以前のバージョンのmallocが可能になります。

  • キャストは、特にポインターがmalloc()呼び出しから遠く離れて宣言されている場合に、宛先ポインターの型が変更された場合に開発者が型サイズの不整合を識別するのに役立ちます(ただし、最新のコンパイラーと静的アナライザーはキャストを必要とせずにそのような動作について警告できます)。

キャスティングのデメリット

  • ANSI C標準では、キャストは冗長です。

  • キャストを追加すると、mallocのプロトタイプが見つかったヘッダーstdlib.hを含めることができなくなる可能性があります。mallocのプロトタイプがない場合、標準では、Cコンパイラがmallocがintを返すと想定する必要があります。キャストがない場合、この整数がポインターに割り当てられると警告が発行されます。ただし、キャストでは、この警告は生成されず、バグが隠されます。特定のアーキテクチャおよびデータモデル(longおよびpointersが64ビットでintが32ビットである64ビットシステムのLP64など)では、暗黙的に宣言されたmallocが32を返すため、このエラーは実際には未定義の動作を引き起こす可能性があります。実際に定義された関数は64ビット値を返しますが、ビット値。呼び出し規約とメモリレイアウトによっては、スタックが破壊される可能性があります。この問題は、宣言されていない関数が使用されたという警告を一律に生成するため、最近のコンパイラでは見過ごされがちです。そのため、警告は引き続き表示されます。たとえば、GCCのデフォルトの動作では、キャストが存在するかどうかに関係なく、「組み込み関数の互換性のない暗黙の宣言」という警告が表示されます。

  • ポインタのタイプが宣言時に変更された場合、mallocが呼び出されてキャストされるすべての行を変更する必要がある場合もあります。

鋳造なしのmalloc関数は、好適な方法であると最も経験豊富なプログラマがそれを選択、あなたは問題を認識したような方、あなたを使用する必要があります。

つまり、CプログラムをC ++としてコンパイルする必要がある場合(別の言語ですが)、使用結果をキャストする必要がありますmalloc

108
PaulJWilliams 2009-03-04 00:18.

Cでは、voidポインターを他の種類のポインターに暗黙的に変換できるため、キャストは必要ありません。使用することは、それが必要とされる理由があることをカジュアルな観察者に示唆するかもしれません、それは誤解を招くかもしれません。

104
Lundin 2014-03-21 05:53.

の結果をキャストしないでください。キャストするmallocと、コードが無意味に乱雑になるためです。

人々が結果をキャストする最も一般的な理由mallocは、C言語がどのように機能するかについて確信が持てないためです。これは警告サインです:あなたは、特定の言語機構作品は、その後、方法がわからない場合はありません推測を取ります。それを調べるか、StackOverflowで質問してください。

いくつかのコメント:

  • voidポインターは、明示的なキャストなしで他のポインター型との間で変換できます(C11 6.3.2.3および6.5.16.1)。

  • ただし、C ++では、void*と別のポインタ型の間の暗黙的なキャストは許可されません。したがって、C ++では、キャストは正しいはずです。ただし、C ++でプログラミングする場合は、を使用する必要がnewありmalloc()ます。また、C ++コンパイラを使用してCコードをコンパイルしないでください。

    同じソースコードでCとC ++の両方をサポートする必要がある場合は、コンパイラスイッチを使用して違いをマークします。互換性がないため、同じコードで両方の言語標準を使用しようとしないでください。

  • ヘッダーを含めるのを忘れたためにCコンパイラーが関数を見つけることができない場合、それに関するコンパイラー/リンカー・エラーが発生します。したがって、それを含めるのを忘れた場合<stdlib.h>、それは大したことではなく、プログラムを構築することはできません。

  • 25年以上前のバージョンの標準に準拠している古いコンパイラでは、含めるの<stdlib.h>を忘れると危険な動作が発生します。その古代の標準では、目に見えるプロトタイプのない関数は、戻り値の型を暗黙的にに変換したためintです。から結果をmalloc明示的にキャストすると、このバグが隠されます。

    しかし、それは実際には問題ではありません。25年前のコンピューターを使用していないのに、なぜ25年前のコンパイラーを使用するのでしょうか。

95
EFraim 2009-03-04 00:16.

Cでは、void *から他の(データ)ポインタへの暗黙的な変換を取得します。

72
Yu Hao 2013-06-10 07:31.

によって返される値をキャストするmalloc()必要はありませんが、誰も指摘していないように思われるポイントを1つ追加したいと思います。

古代では、つまり、ANSI Cvoid *がポインタのジェネリック型としてを提供する前は、そのchar *ような使用法の型です。その場合、キャストはコンパイラの警告をシャットダウンできます。

参照:C FAQ

55
user3079666 2014-03-29 08:21.

私の経験を追加して、コンピューターエンジニアリングを勉強すると、Cで書いているのを見た2、3人の教授は常にmallocをキャストしていることがわかりますが、私が尋ねたもの(CVが非常に大きく、Cを理解している)は絶対に不要だと言いましたが以前は絶対的に具体的であり、学生を絶対的に具体的であるという精神に陥らせるためだけでした。基本的に、キャストは動作方法に何も変更せず、正確に言うことを実行し、メモリを割り当てます。キャストはそれに影響しません。同じメモリを取得し、誤って他の何かにキャストした場合でも(そしてどういうわけかコンパイラを回避します)エラー)Cは同じ方法でアクセスします。

編集:キャスティングには特定のポイントがあります。配列表記を使用する場合、生成されるコードは、次の要素の先頭に到達するために進む必要のあるメモリの場所の数を認識している必要があります。これは、キャストによって実現されます。このようにして、doubleの場合は8バイト先に進み、intの場合は4バイト先に進むことがわかります。したがって、ポインタ表記を使用しても効果はありません。配列表記では必要になります。

53
user968000 2013-02-08 12:22.

malloc、はを返すため、の結果をキャストする必要はありません。またvoid*、avoid*は任意のデータ型を指すことができます。

37
Slothworks 2015-10-10 07:47.

これは、GNUCライブラリリファレンスマニュアルの内容です。

mallocISO Cはvoid *必要に応じて型を別の型のポインタに自動的に変換するため、キャストなしでの結果を任意のポインタ変数に格納できます。ただし、代入演算子以外のコンテキストで、またはコードを従来のCで実行する場合は、キャストが必要です。

そして実際、ISO C11標準(p347)はそう言っています:

割り当てが成功した場合に返されるポインタは、基本的な配置要件を持つ任意のタイプのオブジェクトへのポインタに割り当てられ、割り当てられたスペース内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用できるように適切に配置されます(スペースは明示的に割り当て解除されます)

35
Endeavour 2014-07-13 20:42.

voidポインターはジェネリックオブジェクトポインターであり、Cはvoidポインター型から他の型への暗黙的な変換をサポートしているため、明示的に型キャストする必要はありません。

ただし、暗黙の変換をサポートしないC ++プラットフォームで同じコードを完全に互換性のあるものにしたい場合は、型キャストを行う必要があるため、すべてが使いやすさに依存します。

30
swaps 2013-04-27 06:43.

返される型はvoid *であり、参照解除できるようにするために、目的の型のデータポインタにキャストできます。

29
Jeyamaran 2014-03-18 03:16.

プログラミング言語とコンパイラによって異なります。mallocCで使用する場合は、自動的に型キャストされるため、型キャストする必要はありません。ただし、C ++を使用している場合はmallocvoid*型を返すため、castと入力する必要があります。

28
August Karlstrom 2015-09-05 01:52.

C言語では、voidポインターを任意のポインターに割り当てることができるため、型キャストを使用しないでください。「タイプセーフ」な割り当てが必要な場合は、Cプロジェクトで常に使用する次のマクロ関数をお勧めします。

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

これらを配置すると、簡単に言うことができます

NEW_ARRAY(sieve, length);

非動的配列の場合、3番目の必須関数マクロは次のとおりです。

#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])

これにより、配列ループがより安全で便利になります。

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}
18
StephenG 2015-12-05 07:27.

GCCとClangに慣れている人々は甘やかされています。そこにあるのはそれほど良いことではありません。

私は何年にもわたって、私が使用することを要求されてきた驚くほど古くなったコンパイラーにかなり恐怖を感じてきました。多くの場合、企業やマネージャーはコンパイラーの変更に非常に保守的なアプローチを採用しており、新しいコンパイラー(より優れた標準コンプライアンスとコード最適化を備えた)がシステムで機能するかどうかをテストしません。作業中の開発者にとっての実際的な現実は、コーディングするときにベースをカバーする必要があるということです。残念ながら、コードに適用するコンパイラを制御できない場合は、mallocをキャストすることをお勧めします。

また、多くの組織が独自のコーディング標準を適用し、それが定義されている場合はそれが人々が従う方法であるべきだと提案します。明確なガイダンスがない場合、私は標準への順守よりも、どこでもコンパイルする可能性が最も高い傾向があります。

現在の基準では必要ないという議論は非常に有効です。しかし、その議論は現実世界の実用性を省略しています。私たちは、その日の標準だけで支配されている世界でコーディングするのではなく、私が「ローカル管理の現実分野」と呼んでいるものの実用性によってコーディングします。そして、それは時空よりも曲がったりねじれたりしています。:-)

YMMV。

私はmallocのキャストを防御的な操作と考える傾向があります。きれいではなく、完璧ではありませんが、一般的に安全です。(正直なところ、あなたはSTDLIB.H含まれていませんでしたならば、あなたがきたのmallocのキャストよりも多くの問題!)。

16
Noname 2017-08-17 02:25.

いいえ、の結果をキャストしませんmalloc()

通常、にキャストしたり、からキャストしたりvoid *することはありません

そうしないことの典型的な理由は、失敗#include <stdlib.h>が見過ごされる可能性があることです。C99が暗黙の関数宣言を違法にしたため、これは長い間問題ではなくなりました。したがって、コンパイラが少なくともC99に準拠している場合は、診断メッセージが表示されます。

しかし、不要なポインタキャストを導入しない理由はるかに強力です。

Cでは、ポインタのキャストはほとんどの場合エラーです。これは、次のルールによるものです(N1570の§6.5p7、C11の最新ドラフト)。

オブジェクトの格納値には、次のいずれかの型を持つ左辺値式によってのみアクセスする必要があります。—
オブジェクト
の有効型と互換性のある型
— —オブジェクトの有効型と互換性のある型の修飾バージョン—オブジェクトの有効な型に対応する符号付きまたは符号なしの型で
ある型—オブジェクトの有効な型の修飾バージョンに対応する符号付きまたは符号なしの型である型—1
つを含む集合体または共用体型そのメンバー(再帰的に、サブアグリゲートまたは含まれている共用体のメンバーを含む)の中の前述のタイプの、または
—文字タイプ。

これは、厳密なエイリアシングルールとも呼ばれます。したがって、次のコードは未定義の動作です。

long x = 5;
double *p = (double *)&x;
double y = *p;

そして、時には驚くべきことに、以下も同様です。

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

ポインタをキャストする必要がある場合もあります厳密なエイリアシングルールを考えると、非常に注意する必要があります。したがって、コード内でポインターがキャストされた場合は、その有効性を再確認する必要があります。したがって、不要なポインタキャストを書き込むことはありません。

tl; dr

一言で言えば:Cには、のでどんなの発生ポインタキャストは、特別な注意が必要なコードのための赤い旗を上げる必要があり、あなたは書くべきではありません不要なポインタのキャストを。


サイドノート:

  • ポインタを出力する場合など、実際にキャストが必要な場合がありvoid *ます。

    int x = 5;
    printf("%p\n", (void *)&x);
    

    printf()は可変個引数関数であるため、ここではキャストが必要です。したがって、陰関数変換は機能しません。

  • C ++では、状況が異なります。派生クラスのオブジェクトを処理する場合、ポインタ型のキャストはやや一般的(かつ正しい)です。したがって、それはC ++、およびからの変換は、その意味がvoid *あるではない暗黙。C ++には、さまざまな種類のキャストがあります。

15
Kaz 2016-03-30 14:23.

型システムの醜い穴の不承認を示すためにキャストを挿入しました。これにより、悪い変換を引き起こすためにキャストが使用されていなくても、次のスニペットなどのコードを診断なしでコンパイルできます。

double d;
void *p = &d;
int *q = p;

それが存在しなかったら(そしてC ++には存在しなかったら)、キャストしました。それは私の好みとプログラミングの政治を表しています。私はポインターをキャストするだけでなく、効果的に投票をキャストし、愚かさの悪魔をキャストしています。私が実際に 愚かさを追い出すことができないならば、少なくとも私に抗議のジェスチャーでそうしたいという願いを表明させてください。

実際、mallocを返す関数でラップ(およびフレンド)unsigned char *することvoid *をお勧めします。基本的に、コードで使用することはありません。任意のオブジェクトへの一般的なポインタが必要な場合は、char *またはを使用unsigned char *し、両方向にキャストします。ふけることができる1つの緩和は、おそらく、キャストのような機能memsetmemcpyキャストなしの機能を使用することです。

キャストとC ++の互換性のトピックについては、CとC ++の両方としてコンパイルされるようにコードを記述した場合(この場合、以外のものに割り当てるときにの戻り値キャストする必要があります)、非常に役立つことができます。あなた自身のためのもの:C ++としてコンパイルするときはC ++スタイルのキャストに変換されるキャストにマクロを使用できますが、CとしてコンパイルするときはCキャストに還元できます:mallocvoid *

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

これらのマクロに準拠している場合grepは、コードベースでこれらの識別子を検索するだけで、すべてのキャストがどこにあるかがわかるため、それらのいずれかが正しくないかどうかを確認できます。

その後、定期的にC ++でコードをコンパイルすると、適切なキャストの使用が強制されます。たとえばstrip_qualconstまたはを削除するためだけに使用volatileしたが、型変換が含まれるようにプログラムが変更された場合、診断が表示され、キャストの組み合わせを使用して目的の変換を取得する必要があります。

これらのマクロを順守するのに役立つように、GNU C ++(Cではありません!)コンパイラには美しい機能があります。Cスタイルのキャストのすべての発生に対して生成されるオプションの診断です。

     -Wold-style-cast(C ++およびObjective-C ++のみ)
         非void型にキャストされた古いスタイル(Cスタイル)が使用されている場合は警告します
         C ++プログラム内。新しいスタイルのキャスト(dynamic_cast、
         static_cast、reinterpret_cast、およびconst_cast)の脆弱性は低くなります
         意図しない効果になり、検索がはるかに簡単になります。

CコードがC ++としてコンパイルされる場合は、この-Wold-style-castオプションを使用(type)して、コードに忍び寄る可能性のあるキャスト構文のすべての出現箇所を見つけ、上記のマクロの中から適切な選択肢に置き換えることで、これらの診断をフォローアップできます(または必要に応じて組み合わせ)。

この変換の処理は、「クリーンC」で作業するための単一の最大のスタンドアロンの技術的正当化です。CとC ++の方言を組み合わせたものであり、技術的にはの戻り値のキャストを正当化しますmalloc

15
proski 2016-06-29 21:30.

私はキャストをすることを好みますが、手動ではありません。私のお気に入りは、使用しているg_newg_new0のglibからマクロ。glibを使用しない場合は、同様のマクロを追加します。これらのマクロは、型の安全性を損なうことなくコードの重複を減らします。型を間違えると、void以外のポインター間で暗黙のキャストが発生し、警告(C ++ではエラー)が発生します。g_newとを定義するヘッダーを含めるのを忘れるとg_new0、エラーが発生します。g_newg_new0は異なり、どちらも同じ引数mallocを取りますcalloc。追加0するだけで、初期化されていないメモリを取得できます。コードは、変更なしでC ++コンパイラでコンパイルできます。

14
user877329 2015-06-13 05:23.

可能な場合はいつでも、Cでプログラミングするときに行う最善のこと:

  1. すべての警告をオンにしてCコンパイラでプログラムをコンパイルし、-Wallすべてのエラーと警告を修正します
  2. として宣言された変数がないことを確認してください auto
  3. その後でC ++コンパイラを使ってコンパイル-Wallして-std=c++11。すべてのエラーと警告を修正します。
  4. ここで、Cコンパイラを使用して再度コンパイルします。これで、プログラムは警告なしにコンパイルされ、バグが少なくなります。

この手順により、C ++の厳密な型チェックを利用できるため、バグの数を減らすことができます。特に、この手順では、含めるstdlib.h必要があります。そうしないと、次のようになります。

malloc このスコープ内で宣言されていません

また、結果をキャストするように強制します。そうしmallocないと、

からvoid*への無効な変換T*

またはあなたのターゲットタイプが何であれ。

私が見つけることができるC ++の代わりにCで書くことからの唯一の利点は

  1. Cには明確に指定されたABIがあります
  2. C ++は、より多くのコードを生成する可能性があります[例外、RTTI、テンプレート、ランタイムポリモーフィズム]

静的多型機能と一緒にCに共通のサブセットを使用すると、理想的な場合には2番目の短所がなくなることに注意してください。

C ++の厳密なルールが不便だと思う人のために、推定型でC ++ 11機能を使用できます。

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...
12
Noname 2015-09-11 05:58.

キャストはCではなくC ++専用です。C++コンパイラを使用している場合は、Cコンパイラに変更することをお勧めします。

10
Aashish 2017-10-04 03:13.

mallocのキャストはCでは不要ですが、C ++では必須です。

次の理由により、Cではキャストは不要です。

  • void * Cの場合、は自動的かつ安全に他のポインタタイプに昇格します。
  • を含めるのを忘れた場合、エラーを非表示にすることができます<stdlib.h>。これにより、クラッシュが発生する可能性があります。
  • ポインタと整数のサイズが異なる場合は、キャストによって警告を非表示にしているため、返されたアドレスのビットが失われる可能性があります。
  • ポインタのタイプが宣言時に変更された場合、malloc呼び出されてキャストされるすべての行を変更する必要がある場合もあります。

一方、キャストはプログラムの移植性を高める可能性があります。つまり、Cプログラムまたは関数をC ++としてコンパイルできます。

9
iec2011007 2015-07-29 19:53.

voidポインターの背後にある概念は、mallocがvoidを返す理由である任意のデータ型にキャストできるということです。また、自動型キャストに注意する必要があります。したがって、ポインタをキャストする必要はありますが、キャストする必要はありません。コードをクリーンに保つのに役立ち、デバッグに役立ちます

9
dhana govindarajan 2016-07-19 00:36.

voidポインターはジェネリックポインターであり、Cはvoidポインター型から他の型への暗黙的な変換をサポートしているため、明示的に型キャストする必要はありません。

ただし、暗黙の変換をサポートしないC ++プラットフォームで同じコードを完全に互換性のあるものにしたい場合は、型キャストを行う必要があるため、すべてが使いやすさに依存します。

9
Mohit 2016-11-09 00:09.
  1. 他に述べたように、Cには必要ありませんが、C ++には必要です。

  2. キャストを含めると、Cプログラムまたは関数をC ++としてコンパイルできる場合があります。

  3. Cでは、void *が自動的かつ安全に他のポインタ型にプロモートされるため、これは不要です。

  4. ただし、キャストした場合、stdlib.hを含めるのを忘れると、エラーが非表示になる可能性があり ます。これによりクラッシュが発生する可能性があります(さらに悪いことに、コードのまったく異なる部分で後でクラッシュが発生することはありません)。

    stdlib.hにmallocのプロトタイプが含まれているため、が見つかりました。mallocのプロトタイプがない場合、標準では、Cコンパイラがmallocがintを返すと想定する必要があります。キャストがない場合、この整数がポインターに割り当てられると警告が発行されます。ただし、キャストでは、この警告は生成されず、バグが隠されます。

4

この質問は意見に基づく虐待の対象です。

時々私はそのようなコメントに気づきます:

mallocの結果をキャストしますか?

または

mallocの結果をキャストしますか?

OPがキャストを使用する質問について。コメント自体には、この質問へのハイパーリンクが含まれています。

それはである任意の可能な方法は不適切と間違ったとしても。それが本当に自分自身のコーディングスタイルの問題である場合、正しいことも悪いこともありません。


なんでこんなことが起こっているの?

これは2つの理由に基づいています。

  1. この質問は確かに意見に基づいています。技術的には、質問は数年前に意見に基づいて閉じられるべきでした。「ドI」または「DoがないI」または同等の「万一I」や「べきではない私が」という質問、あなただけの答えは自分の意見の姿勢なしに集中することはできません。質問を閉じる理由の1つは、ここによく示されているように、「意見に基づく回答につながる可能性がある」ためです。

  2. 多くの回答(@unwindの最も明白で受け入れられている回答含む)は、完全にまたはほぼ完全に意見に基づいており(キャストまたは繰り返しを行うとコードに追加される不思議な「混乱」が悪い)、表示されますキャストを省略する明確で焦点を絞った傾向。彼らは一方のキャストの冗長性について議論しますが、さらに悪いことに、プログラミング自体のバグ/失敗によって引き起こされたバグを解決することを主張します-#include <stdlib.h>使用したい場合はそうではありませんmalloc()


私の個人的な意見を少なくして、議論されたいくつかの点の本当の見方をもたらしたいと思います。特に注意する必要があるいくつかのポイント:

  1. 自分の意見に陥るような非常に影響を受けやすい質問には、中立的な賛否両論の答えが必要です。短所や長所だけではありません。

    長所と短所の良い概要は、この回答に記載されています:

    https://stackoverflow.com/a/33047365/12139179

    (私は個人的にこれをその理由のためにこれまでのところ最良の答えだと考えています。)


  1. キャストの省略を理由としてせいぜい遭遇する1つの理由は、キャストがバグを隠す可能性があることです。

    この質問に示されているように、誰かが暗黙の宣言malloc()を使用して、int(暗黙の関数はC99以降標準からなくなった)とを返す場合sizeof(int) != sizeof(int*)

    このコードが64ビットアーキテクチャでセグメンテーション違反を起こすのに、32ビットでは正常に機能するのはなぜですか?

    キャストはバグを隠します。

    これは真実ですが、キャストの省略はさらに大きなバグの前向きな解決策にすぎないため、ストーリーの半分しか示していません-をstdlib.h使用する場合は含まれませんmalloc()

    これは決して深刻な問題にはなりません。

    1. C99以上(推奨され、必須である必要があります)に準拠したコンパイラーを使用し、

    2. コードでstdlib.h使用malloc()したいときに、を含めるのを忘れていないわけではありません。これは、それ自体が大きなバグです。


  1. キャストはC ++で義務付けられているため、CコードのC ++準拠について議論する人もいます。

    まず第一に、一般的に言うと、CコードをC ++コンパイラでコンパイルすることは良い習慣ではありません。

    CとC ++は、実際には、セマンティクスが異なる2つの完全に異なる言語です。

    ただし、CコードをC ++に準拠させる必要がある場合、またはその逆の場合は、キャストの代わりにコンパイラスイッチを使用してください。

    キャストは冗長または有害でさえあると宣言される傾向があるので、これらの質問に焦点を当てたいと思います。キャストが有用または必要でさえある理由を説明します。


  1. コード、それぞれ割り当てられたポインターのタイプ(およびそれに伴うキャストのタイプ)が変更された場合、キャストは有益ではない可能性がありますが、これはほとんどの場合ありそうにありません。次に、すべてのキャストも維持/変更する必要があります。コード内でメモリ管理関数を数千回呼び出すと、これは実際に要約され、保守効率が低下する可能性があります。

概要:

事実は、割り当てられたポインタが基本的な配置要件のオブジェクト(すべてのオブジェクトのほとんどを含む)を指している場合、キャストはC標準(ANSI-C(C89 / C90)以降)に従って冗長であるということです。

この場合、ポインタは自動的に整列されるため、キャストを行う必要はありません。

「aligned_alloc、calloc、malloc、realloc関数への連続呼び出しによって割り当てられるストレージの順序と連続性は指定されていません割り当てが成功した場合に返されるポインターは、適切に整列されているため、任意のタイプのオブジェクトへのポインターに割り当てることができます。基本的な配置要件であり、割り当てられたスペース内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用されます(スペースが明示的に割り当て解除されるまで)。」

出典:C18、§7.22.3/ 1


基本的な配置とは、以下の有効な配置です_Alignof (max_align_t)。基本的な配置は、すべての保存期間のオブジェクトの実装によってサポートされるものとします。次のタイプの配置要件は、基本的な配置でなければなりません。

—すべてのアトミック、修飾、または非修飾の基本型。

—すべてのアトミック、修飾、または非修飾の列挙型。

—すべてのアトミック、修飾、または非修飾のポインター型。

—要素タイプに基本的な配置要件があるすべての配列タイプ; 57)

—第7項で完全なオブジェクトタイプとして指定されているすべてのタイプ。

—すべての構造体または共用体タイプ。そのすべての要素には基本的な配置要件のある型があり、どの要素にも基本的な配置ではない配置を指定する配置指定子はありません。

  1. 6.2.1で指定されているように、後の宣言は前の宣言を隠す可能性があります。」

出典:C18、§6.2.8/ 2

ただし、拡張アライメント要件の実装定義オブジェクトにメモリを割り当てる場合は、キャストが必要になります。

拡張された位置合わせはより大きなアラインメントによって表されます_Alignof (max_align_t)。拡張アライメントがサポートされているかどうか、およびそれらがサポートされているストレージ期間は実装によって定義されます。拡張アライメント要件のあるタイプは、オーバーアライメントタイプです58)。

ソース。C18、§6.2.8/ 3

他のすべては、特定のユースケースと自分の意見の問題です。

自分の教育方法に注意してください。

これまでに行ったすべての回答(および失敗を示す可能性のあるコメント)を最初に注意深く読んmalloc()でから、特定のケースで結果をキャストしない場合は、独自の意見を作成することをお勧めします。

ご注意ください:

その質問に対する正しい答えと間違った答えはありません。それはスタイルの問題であり、あなた自身があなたがどちらの方法を選ぶかを決定します(もちろんあなたが教育や仕事によって強制されていない場合)。そのことに注意し、だまされないようにしてください


最後の注意:私は最近、この質問を意見ベースとして閉じることに投票しました。これは実際に何年もの間必要とされています。クローズ/リニューアルの権限をお持ちの方もぜひご参加ください。

0
pasignature 2020-03-06 05:56.

私にとっては、ここでテイクホームおよび結論は、鋳造ということであるmallocCには全く必要ありませんが、あなたはしかしキャスト場合、それが影響を与える文句を言わないmallocmalloc、まだあなたにあなたの要求恵まれメモリ空間を割り当てます。もう1つの持ち帰りは、人々がキャストを行う理由または理由の1つです。これは、CまたはC ++で同じプログラムをコンパイルできるようにするためです。

他の理由もあるかもしれませんが、他の理由は、ほぼ確実に、遅かれ早かれ深刻な問題にあなたを着陸させるでしょう。

0
ivan.ukr 2020-05-22 21:03.

Cでキャストすることはできますが、必須ではありません。そのコードがC ++としてコンパイルされている場合は、キャストする必要があります。

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

オーケーグッド770HPランボルギーニセンテナリオは十分に正気ではない

オーケーグッド770HPランボルギーニセンテナリオは十分に正気ではない

ランボルギーニの創設者であるフェルッチオランボルギーニが100歳になるのは毎日ではありません(そうです、彼は死んでいて、まだ死んでいると思います。

彼らが買った1台の車からAppleの車の計画について私たちが推測できること

彼らが買った1台の車からAppleの車の計画について私たちが推測できること

Appleが自動車分野に参入するという噂はかなり前から渦巻いており、AppleウォッチャーがSixtyEight Researchという会社がAppleの自動車研究開発のシェル会社である可能性が高いと判断したとき、その渦巻きは本当に渦巻いた。また、会社が購入した車は1台だけであることが知られており、その車はAppleが何を考えているかについての手がかりでいっぱいになる可能性があることも伝えています。

天文学者は太陽系の9番目の惑星の新しい証拠を見つけます

天文学者は太陽系の9番目の惑星の新しい証拠を見つけます

太陽系の外側にある架空の大きな物体である惑星Xの探索は、何十年にもわたって人間を魅了してきました。その検索の最新の章は、地球の10倍の大きさで、公転周期が15であるほど遠くにある惑星を指しています。

キャムニュートン、ゴッドダム

キャムニュートン、ゴッドダム

カムニュートンは昨日、簡単な265ヤードと3回のタッチダウンでファルコンズを引き裂き、別の素晴らしいゲームをしました。その日のハイライトは、上のタッチダウンスローでした。これは、視聴するたびにばかげているだけです。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language