【问题标题】:Implicit function-pointer conversions隐式函数指针转换
【发布时间】:2018-09-25 14:51:16
【问题描述】:

根据 tcc、gcc 和 clang 的经验,一个指向 返回 RetTp 的旧式函数和指向任何原型的指针 返回RetTp 的函数可以相互隐式转换:

//compiles without warnings
typedef void RetTp;
RetTp oldfn(){};
RetTp newfn(int X){};
RetTp (*oldfnp)() = newfn;
RetTp (*newfnp)(int X) = oldfn;

C 标准中有什么东西可以保证这种行为还是只是一个扩展?

【问题讨论】:

  • 调用是一样的。唯一的问题是如何正确传递参数。当你打电话给他们时,你可能会收到警告。顺便说一句,您已关闭警告 - 您没有返回并且有未使用的参数
  • RetTp oldfn(){}; -->> RetTp oldfn(void){};
  • C 2011 [N1570] 6.5.16.1 1 列出了赋值表达式的约束,第三个约束适用于函数指针,要求它们兼容。 6.7.6.3 15 指定了使函数类型兼容的原因,但是我现在写答案太复杂了。它确实允许具有参数列表的类型与没有参数列表的类型兼容,前提是满足某些条件。
  • 据我所知,根据 N1570 应该没问题。但是,您应该知道,如果您将旧式声明与包含参数类型列表的函数定义混合使用,您应该尽量坚持使用intdouble。将 32 位 int 传递给需要 64 位 long can cause problems for example 的函数。从理论上讲,这只是 UB 在起作用,但实际上,这是原型存在的原因,也是我们应该尽可能使用它们的原因。

标签: c language-lawyer


【解决方案1】:

保证转换的隐式性。

6.5.16.1p1 声明赋值有效,如果(除其他外)“...两个操作数都是指向兼容类型的合格或不合格版本的指针...”(“... , 并且左边指向的类型具有右边指向的类型的所有限定符")。

6.7.6.3p15 使函数类型兼容:

对于要兼容的两种函数类型,两者都应指定 兼容的返回类型。146) 此外,参数类型列表,如果 两者都存在,应在参数数量和使用中达成一致 省略号终止符;相应的参数应有 兼容的类型。如果一种类型有参数类型列表,而另一种 类型由不属于 a 的函数声明符指定 函数定义并且包含一个空标识符列表, 参数列表不应有省略号终止符和类型 每个参数应与产生的类型兼容 应用默认参数提升。如果一种类型有 参数类型列表,其他类型由函数指定 包含(可能为空的)标识符列表的定义,两者 参数的数量和每个参数的类型应一致 原型参数应与产生的类型兼容 从应用默认参数提升到类型 对应的标识符。 (在确定类型 兼容性和复合类型,每个参数声明 函数或数组类型被视为具有调整后的类型,并且每个 使用限定类型声明的参数被视为具有 其声明类型的非限定版本。)

【讨论】:

    猜你喜欢
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-24
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多