Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言编程。为什么函数指针会破坏优化_C_Optimization_Function Pointers - Fatal编程技术网

C语言编程。为什么函数指针会破坏优化

C语言编程。为什么函数指针会破坏优化,c,optimization,function-pointers,C,Optimization,Function Pointers,我对使用函数指针的C编程有着爱与恨的关系。我主要在闪存空间有限的微控制器上工作,所以显然我对使用优化非常感兴趣。一方面,函数指针使我的生活变得如此简单,因为我可以编写一个硬件便携式软件模块,用户可以在其中提供函数回调,以执行与硬件相关的操作(例如:用户回调将字节写入串行端口)。通过这种方式,我可以编写95%独立于平台的代码,然后很快就可以移植到新硬件 另一方面,我注意到许多编译器在看到函数指针的任何使用时都会抛出优化。例如,我编写了一个相当通用的函数,它接受枚举类型作为参数,然后为每个枚举类型选

我对使用函数指针的C编程有着爱与恨的关系。我主要在闪存空间有限的微控制器上工作,所以显然我对使用优化非常感兴趣。一方面,函数指针使我的生活变得如此简单,因为我可以编写一个硬件便携式软件模块,用户可以在其中提供函数回调,以执行与硬件相关的操作(例如:用户回调将字节写入串行端口)。通过这种方式,我可以编写95%独立于平台的代码,然后很快就可以移植到新硬件

另一方面,我注意到许多编译器在看到函数指针的任何使用时都会抛出优化。例如,我编写了一个相当通用的函数,它接受枚举类型作为参数,然后为每个枚举类型选择都有一个巨大的switch/case语句来配置寄存器等等,这取决于用户传递给函数的枚举类型。我使用常量文本调用此函数一次,永远不会改变的东西。构建的二进制文件似乎包含操作码来处理每一个开关/案例选择,尽管除了一个案例选择外,所有案例选择都应被视为“死代码”。我使用了不同的优化设置,但为了获得最小的二进制文件,我必须完全注释掉每个“案例”块,除了我需要的一个,闪存利用率降低了约1k字节。如果我不使用函数指针,优化这段代码就没有问题

奇怪的是,我从来没有在我的代码中使用过函数指针和该函数的原型。对于我使用的函数指针原型,指针在静态函数启动时建立一次,然后再也不会建立(另一个常量文本赋值)。我知道我可能可以在所有地方使用#defines来实现相同的设计目标,但让我感到恼火的是,这些工具无法根据我的代码解释什么是可能的/不可能的

我可以看到这样的情况:你有一个函数指针,一些你无法预测的动态事物执行函数(例如,一个人输入一个终端,你不知道高级参数是什么)


当函数指针被使用时,即使是以可预测的方式使用,编译器也会努力进行优化,这有什么好的原因吗?

没有看到您的代码,我无法得出任何明确的结论,但以下是我从自己的经验中了解到的

即使函数是静态的并且只调用一次,指针也会在运行时初始化。编译器无法优化直到运行时才知道地址的函数指针

当函数存在于其他翻译单元中时,它也不能优化掉函数指针;如果函数在翻译单元之外,它不知道它们在哪里,只知道它们已经被声明了;这是链接器的工作来处理。我相信从理论上讲,处理这个问题应该是可能的,但我不确定是否有任何实现可以做到这一点


然而,有些编译器可以优化函数指针(我想到的是MSVC),如果它知道所有地址的位置,并且函数指针是在编译时初始化的。

没有看到您的代码,我无法得出任何明确的结论,但以下是我从自己的经验中了解到的

即使函数是静态的并且只调用一次,指针也会在运行时初始化。编译器无法优化直到运行时才知道地址的函数指针

当函数存在于其他翻译单元中时,它也不能优化掉函数指针;如果函数在翻译单元之外,它不知道它们在哪里,只知道它们已经被声明了;这是链接器的工作来处理。我相信从理论上讲,处理这个问题应该是可能的,但我不确定是否有任何实现可以做到这一点


但是,如果某些编译器知道所有地址的位置,并且函数指针是在编译时初始化的,则可以优化函数指针(我想到的是MSVC)。

基本问题是单独编译——当您使用语言(如C)时当不同的源文件分别编译,然后由单独的链接器链接在一起时,编译器优化器在运行时不知道其他编译单元中的任何内容(这些编译单元可能还没有编写!),因此,它无法知道指针未被修改和/或函数未使用任何其他参数调用

一个可能的解决方案是链接时间优化——如果您的开发套件支持的话


另一种方法是将所有内容强制放入一个编译单元,并使所有内容
都是静态的
,以便编译器知道没有其他编译单元可以引用它。这可能会让优化器做得更好。

基本问题是单独编译——如果您有一种语言(如C),其中不同的源文件分别编译,然后由单独的链接器链接在一起,编译器优化器在运行时不知道其他编译单元中的任何内容(那些编译单元可能还没有被编写!),因此它无法知道指针没有被修改和/或函数没有被任何其他参数调用

一个可能的解决方案是链接时间优化——如果您的开发套件支持的话


另一种方法是将所有内容强制放在一个编译单元中,并使所有内容
都是静态的
,这样编译器就不知道其他编译单元可以引用它。这可能会让优化器做得更好。

编译器被困在DWI(照我说的做)和DWIM(照我的意思做)之间。您的函数代码表示可以使用许多可能的参数值调用函数,并且应该执行dif