23

いくつかのチュートリアルに従い、関数ポインターについて読んでいるうちに、明らかに ISO C で void ポインターを関数ポインターに割り当てることは未定義であることがわかりました。コンパイル時に受け取った警告を解決する方法 (たとえば、コーディングのより良い方法) または私はそれを無視する必要がありますか?

警告:

ISO C forbids assignment between function pointer and 'void *' [-pedantic]

コード例:

void *(*funcPtr)();
funcPtr = GetPointer();

GetPointer は void ポインタ EG を返す関数です

void *GetPointer();
4

3 に答える 3

8

いいえ。コンパイラは正しく、あなたもそうです。C89 と C99 では、データ ポインター (つまりvoid *) と関数ポインターの間で変換できないため、警告を解決する唯一の方法は、関数から関数ポインターを返すことです。

(ただし、実際にはこれは警告にもかかわらず機能し、標準ライブラリにもこの矛盾があることに注意してください-dlsym()関数は関数ポインターを取得するために使用されますが、戻りますvoid *-したがって、基本的に警告を無視できます。動作しますが、厳密に言えば、ここでは動作は未定義です。)

于 2013-01-03T06:50:04.820 に答える
4

glibを使用してこの問題に遭遇しました。GSList などの Glib データ構造には通常、void *data というフィールドがあります。関数をリストに保存したかったのですが、次のようなエラーが大量に発生しました。

warning: ISO C forbids passing argument 2 of ‘g_slist_append’ between function pointer and ‘void *’ [-pedantic]

この例では、 gcc -Wall -ansi -pedantic を使用して一連の警告を生成します

typedef int (* func) (int);

int mult2(int x)
{
    return x + x;
}

int main(int argc, char *argv[])
{
    GSList *functions = NULL;
    func f;

    functions = g_slist_append(functions, mult2);
    f = (func *) functions->data;
    printf("%d\n", f(10));
    return 0;
}

したがって、関数を構造体でラップすると、すべての警告が消えます。

struct funcstruct {
    int (* func) (int);
};

int mult2(int x)
{
    return x + x;
}

int main(int argc, char *argv[])
{
    GSList *functions = NULL;
    struct funcstruct p;
    p.func = mult2;

    functions = g_slist_append(functions, &p);
    p = * (struct funcstruct *) functions->data;
    printf("%d\n", p.func(10));
    return 0;
}

これは、いくつかの警告を非表示にするためのかなりの追加コードであることに議論の余地がありますが、私のコードが警告を生成するのは好きではありません。また、上記はおもちゃの例です。私が書いている実際のコードでは、関数のリストを構造体でラップすると非常に便利であることがわかりました。

これに問題があるのか​​ 、それとももっと良い方法があるのか​​ 知りたいです。

于 2013-05-07T10:34:09.290 に答える