2

私のコードでは、ラムダとしていくつかの関数を使用する必要があります。たとえば、に提供する必要がありますqsort
したがって、タイプの関数を渡したときint、プログラムは正常に機能していました。しかし、タイプの別の関数も追加するとdouble、エラーメッセージが表示されました。

1.c:44:29:エラー:バイナリ<へのオペランドが無効です(「double*」と「double」があります)

行から:

return (*getter)(a) < target

getterポインタはどこにありますか:

double get_sex(struct human* a) { // it's the second function I've passed
    return a->sex;
}

私が渡した2つの関数の唯一の違いは、最初の関数がでintあり、2番目の関数がであるということですdouble

sometype somefunction (some parameters,
        int *comparator(struct human*, double, double *(struct human*)),
        double *getter(struct human*) ) {
    ....
}

私はそれを調べ始めてsizeof、どういうわけかコード(*getter)(*a)が8ではなく4バイトを返すので、それはdoubleではなくポインタでなければならないことを発見しました。そのため、エラーメッセージが表示されました。例としてウィキペディア
にアクセスし、追加のを見つけました。それらを追加しましたが、8バイトを返し、正常に動作します。()

        double (*getter)(struct human*) ) {

だから問題は:なぜ私は周りに括弧を追加する必要がありますgetterが、周りには追加しないのcomparatorですか?関数が?!doubleの代わりに戻る理由は何ですか?int
それは私が聞いたことがない構文の詳細についての何かです。

(私は、すでにインストールされているWindowsで見つけたコンパイラーを使用しています– PerlインタープリターStrawberryから)

4

3 に答える 3

2

あなたの問題はそれから来ます:

double *getter(struct human*)

暗黙的に次のように変換されます。

double *(*getter)(struct human*)

これが、比較できないためにエラーが発生する理由です(double *)double

intポインタ(int *)がキャストされintて比較できるため、問題はありません。ただし、コンパイラは、ポインタから整数への暗黙の変換について警告する必要があります。

ここでの問題は、このような方法で関数ポインタパラメータを宣言できることを私が見たことがないということです。私はコードを書き込もうとしましたが、どうやらそれは機能しているようです。ただし、これはGCCの非標準的な動作である可能性があります。関数へのポインタを定義する正しい方法は、括弧を使用することです。つまり

double (*getter)(struct human*)  /* 'getter' is a pointer to function taking
                                    struct human and returning double */
于 2012-11-28T20:32:58.960 に答える
2

この式では:

int myfunc( double *getter(struct human*) );

...関数型(doubleへのポインタを返す関数型)getterがあります。この間:

int myfunc( double (*getter)(struct human*) );

...関数ポインタ型(doubleを返す関数型へのポインタ)があります。

ほとんどの場合、関数型はほぼ瞬時に関数ポインター型に減衰するため、関数型と関数ポインター型は基本的に同じように機能します。私はこれが標準がここで言っていることだと信じています:(C99、6.3.2.1 / 4):

関数指定子は、関数型を持つ式です。sizeof演算子または単項&演算子のオペランドである場合を除き、「関数戻り型」型の関数指定子は、「関数戻り型へのポインター」型の式に変換されます。

だから、あなたの表現:

return (*getter)(a) < target;

...必要に応じて、標準に従って、getter関数型から関数ポインタ型(型の)に減衰します。double * (*)(struct human*)double (*)(struct human*)

関数をに渡すとすぐにsomefunction、次のような互換性のないタイプであるという警告が表示されます。

警告:互換性のないポインタ型から「somefunction」の引数2を渡します

また、詳細についてはこの回答と、この興味深い回答を参照しください

于 2012-11-28T20:59:40.023 に答える
0

すべてのコードを提供しているわけではないので、次のようなことをしていると推測しています。

if (comparator(h, val, getter)) { ... }

ここで、コンパレータには次のものが含まれます。

return getter(h) < val;

またはそのようなもの。

ここで重要なのは、getterの結果が演算子によって使用されること<です。一方、コンパレータの結果はブール値に変換されます(実際には、これはCです。しかし、同じ考えです)。また、任意のポインタをブール値(つまり、整数)に暗黙的に変換できます。警告を出さずに。

だから何が起こるかです:

  1. コンパレータはを返しますがint

  2. 発信者はを期待していint*ます。それでも大丈夫です。ポインタと整数は同じ方法で返されます。

  3. int*発信者は、あたかもそれがであるかのように使用したいと考えていますint。これも問題ありません。

したがって、エラーはありません。

さらに、戻り値のゼロ性は、偶発的なキャストと暗黙の変換によって保持されるため、ボーナスとして、正しい答えが得られます。

于 2012-11-28T20:30:44.697 に答える