質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

4181閲覧

malloc()の戻り値をキャストするべきか

Merrifield

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

3クリップ

投稿2020/09/01 00:25

タイトル通りmalloc()の戻り値をキャストするべきかどうか、皆さんの意見をお伺いしたいです。ANSI-Cでは、malloc()の戻り値の型はvoid*になっており、キャストは不要だとは思うのですが、実際には、キャストが書かれているコードを結構見かけます。不要だから余計なものを書かないほうがよいという意見も見たことがあるのですが、皆さんはどう思いますか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

ベストアンサー

不要だから余計なものを書かないほうがよいという意見も見たことがあるのですが

そうですね、うっかり#include <stdlib.h>を忘れた場合、C99未満ではプロトタイプの存在しないmalloc関数がintを返すものとみなされてしまう、という状況(暗黙の関数宣言)も発生します。

キャストしていなければintの返り値をそのままポインタに代入することはできないのでコンパイルエラーとなりますが、明示的にキャストしているとそのままコンパイルを通ってしまうこともありえます。

投稿2020/09/01 01:13

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Merrifield

2020/09/01 01:54

いまさっき、ちょうどおしゃられているような、#include <stdlib.h>を忘れていてキャストをしていなかったため、エラーが出たということが起きました。
rubato6809

2020/09/01 15:33

なるほど、うっかりミスに気づくチャンスになりうる、ですか。 私はキャストが不要と気づいて以来、キャストしなくなりました。void*ならそれが自然でしょう・・・と仲間内に説いてまわったことがあります笑。
guest

0

僕はキャストする派です。
C と C++ とで書き分けるのが面倒だから。

投稿2020/09/01 05:24

episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/09/01 05:50

はじめてmallocに出会って以降,ずっと, int *pBuff = (int*)malloc( 略 ); みたくキャストするものとばかり思っていた. というか,malloc()の戻り値ってのがvoid*じゃなかったような気がする.
episteme

2020/09/01 05:55

昔々はchar*かint*じゃなかったかしら...ひょっとしたらタダのintだったかも(型にテキトーな初期の頃) ANSI-Cあたりでvoid*から任意の*に暗黙変換できるようになったんだっけか。
fana

2020/09/01 06:16 編集

なんかそんな話みたいですね. 私が大学で受けたCの講義では,K&RとANSI-Cな本を併用してたから 私はANSIでvoid*な時代の若者なハズなんだけど,使わされた環境が古かったのかな? (それはそれとして,回答内容は私もそう思うので+を投じてみる)
episteme

2020/09/01 06:30

てかもはや C++ で malloc/free を使うことはめったにないんですけどね... # C とのインタフェースが目的で"渋々"使うくらいでしょか。
guest

0

こんにちは。

どうやら本質的には型キャストの問題のようですね。
C++界隈ではCスタイル・キャスト(C言語のキャスト)は邪悪なので使うべきでないとも言われています。
コンパイラが検出できる記述ミス(≒バグ)をCスタイル・キャストは台無しにするからです。原理はmaisumakunさんが回答されている通りです。

Cスタイル・キャストしかないC言語にこの原則を当てはめることができるケースは稀ですが、今回の質問のケースでは当てはめることができそうです。ならば、「Cスタイル・キャストはできるだけ使わない」原則に従って「キャストしない」が望ましい記述と思います。

なお、キャストしているコードは多いと思います。私もその一人でした。当時は、キャストしないとエラーになるから盲目的にキャストしてました。ベターCとしてC++を使っているとそうなりそうです。

投稿2020/09/01 04:13

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まあ、C言語においてはエラーは出ないのでどっちでもいいです。

が、コードの意図を明確にする、という目的であえてキャストを書きます。
キャストしておけば、代入先の変数の型が想定のものでない場合に、エラーなりワーニングなり出してくれます。
また、後でコードを読む場合にも理解の助けとなってくれますね。

コメントを書くか、というのと同じで、理解しやすくするためには、書いたほうがいいんじゃないの?というていどでいいかとおもいますよ

投稿2020/09/01 01:16

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Cでは省略しても問題ありません。
C++の場合、キャストが無いとコンパイルエラーになります。

投稿2020/09/01 00:35

編集2020/09/01 00:36
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/09/01 00:39

そもそもC++でmallocを使うこと自体、(Cとの互換上やむを得ない場合を除いて)適切でないでしょうし。
退会済みユーザー

退会済みユーザー

2020/09/01 00:46

そうですね。 最近純粋なC触る機会自体が無いので、mallocを触る事が殆ど無いですね…
otn

2020/09/01 01:07

> Cでは省略しても問題ありません。 それは質問者もご存じ。 「文法的にはどっちもありなので、両方見たことがある。皆さんはどう思いますか?」が質問なので、 「私は(書く|書かない)。何故ならば~~」が期待する回答でしょう。 まあ、アンケートなので非推奨質問ですが。
退会済みユーザー

退会済みユーザー

2020/09/01 01:44

なるほど、アンケート的な意図でしたか。 個人的には、C⇔C++のコードの相互運用を考慮するなら、冗長であってもキャストを入れても良いと思っています。(最近C触ってないけど)
guest

0

型変換 - Wikipedia

キャストは型変換をすることで、明示的なものと暗黙的なものがあります。たとえば次は暗黙のキャストです。

C

1int* ptr = malloc(100);

void* 型のポインタを int* 型に変換しています。次のように書くと同じ意味ですが明示的なキャストになります。

C

1int* ptr = (int*)malloc(100);

次のようにポインタ演算する場合、キャストは必要不可欠です。次の iptr + 1cptr + 1 は違う値を指します。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int main() { 5 void* ptr = malloc(100); 6 int* iptr = ptr; 7 char* cptr = ptr; 8 printf("%p %p", cptr + 1, iptr + 1); 9 free(ptr); 10}

malloc でメモリを得る場合、配列などの大きなメモリであることがしばしば考えられます。その場合、アドレス演算が必要になる可能性が高いため、それなりの型にキャストが必要なことが多いでしょう。逆に演算しないなら、そのポインタが示す先の型が何でもよいことを示すため、void* のままでも問題ないと思います。

追記

コンパイラによって暗黙のキャストがされる場合でも明示的キャストをしなければならないかという質問なら、「冗長であるし警告が出ないので、しなくて良い」と答えます。maisumakun さんの回答にあるように、強引なキャストによってバグが見えにくくなることもあります。
した方が良いかという質問なら「どちらでも良いのでチームのコーディング規約に従うか、個人開発の場合は好きな方を使えば良い」と答えます。
自分ならするかという質問なら「私はしない」と答えます。C 言語のソースコードは、C 言語としてコンパイルします。C++ ならもっと C++ らしい書き方をするでしょう。そしてこの質問は C 言語の質問です。

追記

途中からわざわざ導入された書き方なので、制定者たちエキスパートの知見を信じるなら、「使える状況で絶対に明示的キャストを省略してはいけない理由」は少なくともないと思います。むしろ需要があるからこそ供給されたものです。
いくつかの C 言語のコードに明示的キャストが無かった場合、コードを書いた人が明示的キャストを選ばなかった理由はそれぞれあると思いますが、C 言語の歴史に思いをはせるなら、その理由の大半が「古いコードである」または「古い書き方をそのまま使っている」と言って間違いないのではないかと思います。

投稿2020/09/01 01:26

編集2020/09/01 02:36
Zuishin

総合スコア28669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2020/09/01 01:32

C99以降のvoid*型が任意のポインタ型に暗黙変換されることを指している質問かと思われます
Zuishin

2020/09/01 01:33

回答中で任意のポインタ型に暗黙変換していますが、どういうことでしょうか?
yumetodo

2020/09/02 03:57

当初書かれていた > `malloc` でメモリを得る場合、配列などの大きなメモリであることがしばしば考えられます。その場合、アドレス演算が必要になる可能性が高いため、それなりの型にキャストが必要なことが多いでしょう に対して反応したつもりでした。
Zuishin

2020/09/02 04:00

今も書いていますが、まだ意味が分かりません。どのあたりが低評価に相当するんでしょうか?
Zuishin

2020/09/02 04:20

該当する部分は一字一句変わっていないのに低評価が外れましたが、この回答に問題があるわけではなく、誤解による低評価ということですか?
yumetodo

2020/09/02 04:30

当該箇所が最初見たとき、アドレス演算が必要になるケースについて議論したいと思われる質問者の意図からずれているように感じたのですが、**冒頭部分をきちんと読めていなかったこと**とその後の追記を読んで低評価を外しました。 もっと半日くらい寝かせて自分がしっかり理解しているか確認してから低評価するなどして再発防止に努めます。
Zuishin

2020/09/02 04:33

了解しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問