C语言 什么时候写函数f的&f或函数指针fp的 *fp是必要的或有意义的(除了在:sizeof &f)?

6uxekuva  于 2023-05-16  发布在  其他
关注(0)|答案(1)|浏览(162)

从C17标准草案(6.3.2.1 ¶4;删除脚注):

  • function designator* 是一个具有函数类型的表达式。除非它是sizeof运算符或一元&运算符的操作数,否则类型为“function returning type”的函数指示符将转换为类型为“pointer to function returning type”的表达式。
  • 根据我从上面引用中省略的脚注,sizeof f(用于函数指示符f)是不符合标准的。
  • 请注意,C11标准还提到了_Alignof运算符。
  • 请注意,C2 x草案还提到了typeof运算符。

因此(此处:f是函数指示符; fp是一个函数指针):
1.可以将函数的地址表示为&f(显式)或f(短)。

  • 可以这样调用函数:
  • (&f)(args)f(args)
  • fp(args)(*fp)(args)

这里

  • 左侧(&f)(args)/fp(args)与在函数指针上操作的函数调用一致,并且
  • 右边的f(args)/(*fp)(args)与函数调用操作函数(而不是指向函数的指针)的天真假设一致。

从风格上来说

  • this answer&f标记为“始终冗余”,
  • (&f)(args)实际上未使用,并且
  • f/f(args)/fp(args)是最短的样式。

(For为了完整起见(如果其他人想要一个很好的总结),这里有一个更长的表达式列表,等价于f(&f)(*******f)(***&***f)(***&**&f)(&**&***f)(&**&**&f)。)
但是:

什么时候有必要或有意义
*&f(其中f是函数指示符)或
*write *fp(其中fp是函数指针)?

(By“有意义”,我的意思是程序的行为被改变了。

  • 我唯一知道的情况是sizeof &f。(sizeof f是非法的,尽管C语言的GCC方言允许它(至少在12.2.0版),但具有不同的语义:它似乎返回1(?)的案件。为什么?)
  • 我不明白让f自动转换为&f可以简化标准的措辞,并为sizeof f提供有用的语义。(也许这个限制的存在是为了保持与typeof的并行性,typeof作为编译器扩展已经存在了一段时间。
  • 我不知道_Alignof发生了什么。
  • 如果typeof被正式添加到下一个标准中,那么typeof &f/typeof fptypeof f/typeof *fp之间的区别显然是有意义的。
2hh7jdfx

2hh7jdfx1#

由于函数指示符f在许多情况下会自动转换为函数的地址,因此f&f在语义上不同的唯一时间是在不转换时。根据C 2018 6.3.2.1 4,这些是当它是sizeof或一元&的操作数时。因此,我们有:

  • sizeof f需要一个诊断消息,因为它违反了C 2018 www.example.com 1中的约束6.5.3.4(sizeof不应应用于具有函数类型的表达式),并且它的行为不是由C标准定义的(因为违反了约束),而sizeof &f产生指向函数的指针的大小。(sizeof f仍然是符合C 2018 4 7的代码,尽管不是严格符合的,因为存在接受它的C编译器。
  • &f产生f的地址,而& &f需要一个诊断消息,因为它违反了C 2018 www.example.com 1中的约束6.5.3.2(一元&的操作数应该是函数指示符,数组下标或一元*的结果,或者不是位字段或用regiser声明的左值)。我不知道有C编译器接受& &f,所以这不是严格符合的代码,除非我们可以想象并构建一个接受它的C编译器。(& &f中的空格用于分隔标记。否则,&&是一个单独的标记,用于逻辑AND运算符。)

我对GCC接受sizeof f的原因的猜测是,它是允许指针上的地址运算的一部分,甚至是void *和指向函数的指针,以支持在操作系统、调试器、程序加载器和类似的在函数和任意内存上操作的软件中使用的代码。使sizeof f为1是设计GCC的函数指针算法的一部分,以字节为单位进行操作。(这是GCC的一个不必要的特性,因为我们可以通过要求函数和void *的指针首先转换为字符类型的指针来支持它们的算术运算。然而,我认为它是为了支持代码实践而做的,现在已经是遗产了。)
在语法级别上,&ff的不同之处在于更长,因此它可能会违反编译器的环境限制。例如,C 2018 5.2.4.1 1要求编译器在逻辑源代码行中支持4095个字符(至少在一个程序中),因此将f更改为&f可能会使该行超过编译器支持的长度。
对于*fpfp,适用类似的推理:*fp在很多情况下会被转换为fp的等价物,因此只有在不转换时才会出现语义差异。因此,sizeof *fpsizeof fp如上所述不同。然而,对于&&*fp是函数的地址,而&fp是指针的地址。(这假设fp是一个对象,而不是其他不是左值的表达式。如果它不是一个对象,则会引发与上面针对&所讨论的相同的问题。)
*fpfp的环境限制考虑与&ff相同。

相关问题