简体   繁体   English

关于 function 指针采用任意数量的 arguments,如何使 C 编译器安静下来?

[英]How do I quiet the C compiler about a function pointer takes any number of arguments?

I have a function pointer inside a struct that gets dynamically set at runtime to the address of another function in various places in my code.我在一个struct中有一个 function 指针,该指针在运行时动态设置为我代码中不同位置的另一个 function 的地址。 It is defined in my header file like this:它在我的 header 文件中定义如下:

    void *(*run)();

During compile time, I get the following warning about this:在编译期间,我收到以下警告:

    warning: function declaration isn't a prototype

This warning is benign, because the pointer is used in many places in my code to call the function it points to, and everything works just fine.这个警告是良性的,因为在我的代码中的许多地方都使用了指针来调用它指向的 function,并且一切正常。 However, I would really like to silence the warning.但是,我真的很想消除警告。

If I change it to this:如果我将其更改为:

    void *(*run)(void);

I get compile errors whever I use it, because the various functions that make use of the pointer have different numbers of arguments, and saying void inside the parenthesies tells the compiler it accepts no arguments.无论我使用它,我都会遇到编译错误,因为使用指针的各种函数具有不同数量的 arguments,并且括号内的void告诉编译器它不接受 arguments。

I can't use a va_list or anything fancy like that, as this is simply a pointer to another function, and I use a single pointer for them all because it keeps the code clean and simple.我不能使用va_list或任何类似的东西,因为这只是指向另一个 function 的指针,我对它们都使用单个指针,因为它使代码保持简洁。

I can silence the warning with adding this to my compiler flags:我可以通过将其添加到我的编译器标志来使警告静音:

    -Wno-strict-prototypes

But I'd rather not have to disable compiler warnings with flags if I can avoid it.但是,如果可以避免的话,我宁愿不必禁用带有标志的编译器警告。

So my question is: How do I notate this function pointer in the code in such a way that the compiler is satisfied with the fact that it accepts any number of any kind of arguments?所以我的问题是:我如何在代码中注释这个 function 指针,以使编译器对它接受任意数量的任何类型的 arguments 这一事实感到满意?

The code works perfectly.该代码完美运行。 I just want the warning to go away.我只想要 go 的警告。

Store the pointer as a void * and cast to the appropriate function pointer type when necessary?将指针存储为void *并在必要时转换为适当的 function 指针类型? Keep in mind that it isn't necessarily safe to call one type of function pointer as if it were another type, so the warning you're starting out with isn't entirely invalid.请记住,将一种类型的 function 指针调用为另一种类型并不一定安全,因此您开始使用的警告并非完全无效。

You can cast a function pointer like so:您可以像这样转换 function 指针:

void *genericPointer = ...;
void (*fp)(int, int) = genericPointer;
fp(123, 456);

Note that:注意:

  • There's no explicit casting necessary here, as void * can always be cast to any pointer type.这里不需要显式转换,因为void *总是可以转换为任何指针类型。
  • The initial "void" before (*fp) is the return type of the function pointer. (*fp)之前的初始“void”是 function 指针的返回类型。

You are trying to do things clean - ie involve the compiler in checks, but the design you invented simply cannot be clean by its principle.您正在尝试做干净的事情 - 即让编译器参与检查,但是您发明的设计根本无法按照其原理进行清洁。 You cannot involve compiler in prototype checks this way, because you always must know, which parameters to pass at this particular case in runtime.您不能以这种方式让编译器参与原型检查,因为您始终必须知道在运行时的这种特殊情况下要传递哪些参数。 Compiler cannot check this and if you make a mistake, segmentation fault is on the way.编译器无法检查这一点,如果你犯了错误,就会出现分段错误。

But if I remember well, something like this was maybe used also in linux kernel (?).但如果我没记错的话,linux kernel(?)中也可能使用过类似的东西。 The solution is to have a general pointer (like the one you have) and each time you call a particular function you just typecast it to the pointer to function with the particular arguments.解决方案是拥有一个通用指针(就像您拥有的那样),每次调用特定的 function 时,您只需将其类型转换为指向 function 的指针,并带有特定的 ZDBC11CAA5BDA99F77E6FB4DABD882E7。 You may need to typecast it to void * first to silence the compiler again:-)您可能需要先将其类型转换为 void * 以再次使编译器静音:-)

In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. In C, when you call a function without a prototype visible, default argument promotions are applied to all of the arguments that you pass to the function. This means that the types that you actually pass do not necessarily match the types received by the function.这意味着您实际传递的类型不一定与 function 接收的类型匹配。

Eg例如

void (*g)();
void f()
{
    float x = 0.5;
    g(x); // double passed
}

This means that you need to know that the function that you are actually calling has a compatible signature to that implied by the arguments that you are passing after promotion.这意味着您需要知道您实际调用的 function 与您在升级后传递的 arguments 所暗示的签名兼容。

Given that you need to know this in any case you must know the function signature of the actual function being called at the call site which is using the function pointer.鉴于您在任何情况下都需要知道这一点,您必须知道在使用 function 指针的调用站点上调用的实际 function 的 function 签名。 With this knowledge it is usually simpler and cleaner to use a function pointer with the correct prototype and you can avoid default argument promotion entirely.有了这些知识,使用具有正确原型的 function 指针通常更简单、更清晰,并且您可以完全避免默认参数提升。

Note that as you are defining your functions with prototypes, when you assigned a pointer to your function to a function pointer without a prototype you effective converted, say, a void(*)(int, int) to a void(*)() so it is completely correct and desirable to perform the reverse conversion before calling the function.请注意,当您使用原型定义函数时,当您将指向 function 的指针分配给没有原型的 function 指针时,您可以有效地将void(*)(int, int)转换为void(*)()因此在调用 function 之前执行反向转换是完全正确和可取的。 gcc allows both these conversions without emitting any warnings. gcc 允许这两种转换而不会发出任何警告。

Eg例如

void PerformCall( void(*p)() )
{
    if (some_condition)
    {
        // due to extra knowledge I now know p takes two int arguments
        // so use a function pointer with the correct prototype.
        void(*prototyped_p)(int, int) = p;
        prototyped_p( 3, 4 );
    }
}

Try typedefing the function pointer declaration and then have the caller explicityly cast it:尝试 typedefing function 指针声明,然后让调用者显式地转换它:

typedef void *(*run)();

//when calling...
void my_foo() {}

run r = (run)my_foo;

If the different function signatures are known, use a union .如果已知不同的 function 签名,请使用union Otherwise, use a pointer of type void (*)(void) (actually, any function pointer type would do) to hold the generic pointer and convert to the proper type when setting the value and calling the code.否则,使用void (*)(void)类型的指针(实际上,任何 function 指针类型都可以)来保存通用指针并在设置值和调用代码时转换为正确的类型。

Example using a union :使用union的示例:

union run_fn
{
    void *(*as_unary)(int);
    void *(*as_binary)(int, int);
};

struct foo
{
    union run_fn run;
};

void *bar(int, int);
struct foo foo;

foo.run.as_binary = bar;
void *baz = foo.run.as_binary(42, -1);

Example using explicit casts:使用显式强制转换的示例:

struct foo
{
    void (*run)(void);
};

void *bar(int, int);
struct foo foo;

foo.run = (void *(*)(int, int))bar;
void *baz = ((void *(*)(int, int))foo.run)(42, -1);

Don't use a void * to hold function pointers - such a conversion is unspecified by the ISO C standard and may be unavailable on certain architectures.不要使用void *来保存 function 指针 - ISO C 标准未指定此类转换,并且可能在某些架构上不可用。

Ignoring the warning and using your code as-is is actually also a possibility, but keep in mind that any function argument will be subject to the default argument promotions and it's your responsibility that the promoted arguments properly match the declared parameters.忽略警告并按原样使用代码实际上也是一种可能性,但请记住,任何 function 参数都将受到默认参数提升的影响,提升的 arguments 与声明的参数正确匹配是您的责任。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将参数绑定到 C 函数指针? - How do I bind arguments to a C function pointer? 如何在 Fsm 中存储指向带参数的函数的指针? - how to store pointer to function that takes arguments in Fsm? 如何指定一个 C++ 指针指向一个 C function 与未知数量的 ZDBC11CAA5BDA99F77E6FBDED47 - How to specify a C++ pointer to a C function with unknown number of arguments? C-具有函数指针的结构,如何修复“变量数目可变”的警告? - C - struct with a function pointer, how to fix “variable number of arguments” warning? 如果仅在运行时知道参数数目,如何调用函数指针 - How do I call a function pointer where number of arguments if only known at runtime 如何定义一个函数指针,该函数指针具有与给定函数相同的参数并返回值? - How can I define a function pointer that takes the same arguments and return value as a given function? 如何解决有关将函数指针传递给C中的宏的警告? - How do I resolve this warning about passing a function pointer to a macro in C? 如何为接受函数指针的函数提供参数 - How do I give arguments to a function that accepts function pointer 关于消除C中内联函数指针操作的编译器优化? - Compiler optimization about elimination of pointer operation on inline function in C? 编译器优化:C语言中非指针函数参数的const - Compiler Optimization: const on non-pointer function arguments in C
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM