プロが教える店舗&オフィスのセキュリティ対策術

こんにちは。

授業でC原語を習っており、その課題で詰まった所についての質問です。
※以下の関数については可能な限り簡略化しています。


typedef struct {
  char name[10];
  int height;
} Person;

Person *bin_search( const Person *key)
{
  return (&key);
}


以上のような構造体と関数があった場合、bin_searchでkeyを返したいのですが、
return (&key);
では、コンパイルするとその行について
return from incompatible pointer type
warning: function returns address of local variable
とエラーが出てしまいます。

return (key);
return (*key);
などとりあえず試してはみたのですがどれも上手くいきません。

そもそも関数名の前に*(間接演算子?)があること自体がよくわかっていないです……

なので、返り値をどうすれば正しく機能してくれるのか教えていただけるとありがたいです。


※課題で指定されているので、関数頭部については変更しないとします。

A 回答 (12件中1~10件)

>return (key);


>などとりあえず試してはみたのですがどれも上手くいきません。
とありますが「return (key);」の場合「const*」を「*」に変えたというワーニングがでるだけで正しく動くと思いますが?どういった風に上手く行かなかったのでしょうか?

keyには構造体のアドレスが入っています、関数の返却値も同一構造体のアドレスです。そのままkeyを返せば良いだけです。

この回答への補足

「return (key);」の場合、
return discards qualifiers from pointer target type
という警告文が表示されました。
これが、そのワーニングにあたるのでしょうか?

補足日時:2012/05/24 16:40
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
おかげでプログロムは無事実行することが出来ました。

お礼日時:2012/05/25 16:05

その「bin_search」とやらは何をする関数なんでしょうか?



ことと次第によっては「bin_searchでkeyを返したい」が既にはずれである可能性もあります.

この回答への補足

元は、ライブラリ関数のbsearchを自作しようというものでした。
仮引数もいくつかありましたが、最終的にはkey(と同じ構造体の配列)を返せればよいので、このような形にしました。

補足日時:2012/05/24 13:05
    • good
    • 0

*bin_search( const Person *key)



関数の前に*がついていると、関数ポインタになります。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。

お礼日時:2012/05/25 16:04

「関数ポインタ」ってなんでしょうか>#3.

    • good
    • 0

>Person *bin_search( const Person *key)



bin_search関数の戻り値はPerson型へのポインターですね。よって、

>return (&key); // 戻り値の型はPerson **型
>return (*key); // 戻り値の型はPerson 型

これらが正しくないのはわかるのですが、

>return (key);

これもダメでしたか?
そのときのエラーメッセージは、どういう内容でしたか?

# 関数ポインターという用語があることは間違いないが、このシチュエーションで使うものかどうかは微妙。

この回答への補足

「return (key);」の場合、
return discards qualifiers from pointer target type
という警告文が表示されました。

補足日時:2012/05/24 16:40
    • good
    • 0

ポインタはややこしいですが、&や*が付いたらどんな型になるかを落ち着いて考えましょう。




> Person *bin_search( const Person *key)

*がbin_search, keyに付いてますが、考え方としては
「Person *」を返す関数「bin_search」
「const Person *」型の引数「key」です。

とすると、 「&key」は「『const Person *』型へのポインタ(const Person **)」になるので、戻り値の「Person *」とは一致しません。それが
> return from incompatible pointer type
(互換性の無いポインタを返した)というエラーです。

「*key」は「『const Person *』型(= const Personへのポインタ)から参照される実体(const Person)」になるので、戻り値の「Person *」とは一致しません。そもそもポインタでは無いので、エラーメッセージも違っているはずです。

では、「key」はなにか、と言えば、「const Person(=変更できないPerson)へのポインタ」です。
戻り値は「Person(=変更もできるPerson)へのポインタ」なので「一致しません」

Person * → const Person *は暗黙の型変換が行われます。これは、参照先を読み書きできるように扱うか、読み込みのみで扱うかの違いなので、問題はありません。
しかし、逆はできません。

対処法は次のようなものがあります。それぞれに一長一短です。他の部分との組合せ等から、適切なものを選んでください。
・戻り値をconst Person *にする。
・引数をPerson *にする。
・return時に Person *へキャストする。


> warning: function returns address of local variable
これは別の話しです。
keyは、この関数が呼ばれたときに確保され、関数から戻ったら解放される「(関数内で自動の)ローカル変数」です。
&keyは、そのローカル変数のアドレスを示します。
そのローカル変数が解放されたら、その領域がどうなるかはわかりません。すぐに別の変数がその領域を使ってしまうかもしれません。
なので、「受け取ったアドレスが無意味になってるかもしれませんよ。大丈夫ですか?それを意図したプログラムですか?」という警告です。
    • good
    • 0
この回答へのお礼

丁寧で細かい説明ありがとうございました。
おかげでプログロムは無事実行することが出来ました。

お礼日時:2012/05/25 16:01

関数名の前に付いている * は、戻り値のデータ型の一部です。

つまり、この関数の戻り値のデータ型は Person * です。

引数は const Person * なので、警告文
 return discards qualifiers from pointer target type
はデータ型に付いている const を、戻り値で捨てている点を警告しています。
(たぶん、使われているのは gcc でしょうか)

下のように探索結果を返せば警告は出なくなります。key の内容は変えない方が分かりやすいプログラムになるでしょう。戻り値を free() することを忘れないよう注意してください。

Person *bin_search( const Person *key)
{
  Person *value = malloc(sizeof(Person));
  if (value != NULL) {
    ... 二分探索で見つけた値を value にセット ...
  }
  return value;
}


話はそれますが、「二分探索」が課題なのですね。がんばってください。二分探索はシンプルなのに正しく作ることが難しいことで知られています。(最初にアルゴリズムが発表されてから、バグのないプログラムが出版されるまでに16年もかかっている!)

「珠玉のプログラミング」(ジョン・ベントリー, ピアソンエデュケーション, 2000)
「C言語による最新アルゴリズム事典」(奥村晴彦, 技術評論社, 1991)
などの書籍が参考になります。
    • good
    • 0
この回答へのお礼

丁寧で細かい説明とエール、ありがとうございました。
おかげでプログロムは無事実行することが出来ました。

お礼日時:2012/05/25 16:04

検索せずにキーをそのまま返す検索関数って意味あるの?

    • good
    • 0

詳細な説明はほかの方がしてくれているので、別の意見を。



とりあえず、プロトタイプは
Person *bin_search( const Person *key, Person *data, size_t num)
でないとまずいんじゃないかな。

それとプロトタイプからconstを外すというのが一番よいと思いますが
プロトタイプでconstをつけるのは関数の中で値を書き換えないことの
意思表示でもあるので検索系の関数だし、
constをつけたままにして return するときに(Person *)で
キャストしてしまうとか、戻り値そのものを int にして、配列の番号を返す仕様に変更する案もありかと思います。
    • good
    • 0
この回答へのお礼

課題として関数宣言は指定されているので、constは外せなかったんですよ……
説明ありがとうございました。

お礼日時:2012/05/25 16:03

よしんば「実際に検索をする」関数であっても, 「検索キーをそのまま返す」検索関数に意味があると思えないのです>#8.



ふつうは「検索して見付けたもの」を返すのでは?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!