7

重複の可能性:
関数ポインターを別の型にキャストする

実際には関数ポインター定義よりも少ないパラメーターを取る関数で関数ポインターを初期化すると仮定します。関数ポインターを介して呼び出された場合、関数は引き続き正しく実行されますか?

これをgccで試してみたところ、期待どおりに機能しましたが、その動作がコンパイラ/プラットフォーム間で一貫しているのかどうか疑問に思います(環境によっては、スタックに大混乱をもたらす可能性があると思われます):

#include <stdio.h>

typedef void (*myfun)(int, int, int);

void test_a(int x, int y, int z) {
    printf("test_a %d %d %d\n", x, y, z);
}

void test_b(int x, int y) {
    printf("test_b %d %d\n", x, y);
}

int main() {
    myfun fp;
    fp = test_a;
    fp(1, 2, 3);
    fp = (myfun) test_b;
    fp(4, 5, 6);
}
4

4 に答える 4

12

これは未定義の動作です。自己責任。鼻魔を引き起こすと噂されています

ここに画像の説明を入力

于 2012-11-18T21:27:10.807 に答える
5

プログラムの動作は未定義です。それがまったくコンパイルされるという事実は、コンパイラに「これは間違っていますが、とにかく実行してください」と効果的に伝えるキャストによるものです。キャストを削除すると、適切なエラー メッセージが表示されます。

a.c:17:8: error: assignment from incompatible pointer type [-Werror]

(からgcc -Wall -Werror。)

より具体的には、動作は呼び出し規約に依存します。引数がスタック上で「逆」の順序で渡されるプラットフォーム上にいた場合、プログラムは非常に異なる結果を返します。

于 2012-11-18T21:25:19.097 に答える
3

関数呼び出しは未定義の動作です。

(C99, 6.3.2.3p8) 「[...] 変換されたポインターを使用して、ポイント先の型と互換性のない型を持つ関数を呼び出す場合、動作は未定義です。」

参考までに、関数のタイプは次のとおりです。

(C99、6.2.5p20) 「[...] は、指定された戻り値の型を持つ関数を表します。関数型は、その戻り値の型と、そのパラメーターの数と型によって特徴付けられます。」

于 2012-11-18T21:29:14.393 に答える
2

動作するかどうかは、使用されている呼び出し規約によって異なります。

私はそれをお勧めしません。

于 2012-11-18T21:28:59.587 に答える