4

在 Visual Studio 2012 中的函数指针问题之后,我开始怀疑 C 中对函数指针的某些赋值的合法性。

下面的代码编译时会出现警告,正如我所期望的那样,因为分配的函数需要参数比函数指针声明所描述的参数多(GCC 4.8):

#include <stdio.h>

int test(int x, int y)
{
    printf("%d", x);
    printf("%d", y);
    return 0;
}

int main()
{
    int (*test_ptr)(int);
    test_ptr = test;
    test_ptr(1);
    return 0;
}

如果更改代码以使分配的函数需要更少的参数(GCC 4.8),则会出现相同的警告。同样,这是意料之中的。

但是,尽管分配的函数需要 2 个参数而不是 0 ( GCC 4.8 ),但以下代码编译时没有任何警告:

#include <stdio.h>

int test(int x, int y)
{
    printf("%d", x);
    printf("%d", y);
    return 0;
}

int main()
{
    int (*test_ptr)();
    test_ptr = test;
    test_ptr();
    return 0;
}

任何地方都不涉及铸件。

谁能解释这个编译器行为?

4

2 回答 2

9

以下:

int (*test_ptr)();

接受未指定数量的参数,而不是零参数。

对于后者,写

int (*test_ptr)(void);

PS 调用具有零参数的双参数函数会导致未定义的行为。

于 2013-03-27T08:09:44.637 回答
2

从函数指针转换为函数指针是合法的。非法的是调用类型与实际指向的函数不兼容的函数指针。

C99 6.3.2.3 标准杆。8:

指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应与原始指针比较。如果转换后的指针用于调用类型与指向的类型不兼容的函数,则行为未定义

如果您的编译器准确警告未定义的行为,它应该在test_ptr();. 但是不能期望编译器对所有未定义的行为发出警告或只对未定义的行为发出警告。


这个静态分析器(我和其他人一起工作)会尽力警告所有未定义的行为,并且只警告未定义的行为。涉及很多妥协,但在这种特殊情况下:

$ cat > fp.c

int test(int x, int y)
{
    printf("%d", x);
    printf("%d", y);
    return 0;
}

int main()
{
    int (*test_ptr)();
    test_ptr = test;
    test_ptr();
    return 0;
}
$ frama-c -val fp.c
...
fp.c:13:[value] warning: Function type must match type at call site: assert(function type matches)

第 13 行是test_ptr();.

于 2013-03-27T08:13:20.680 回答