编译时计算C ++ v.C 还要考虑tunes.org情况

如何解决编译时计算C ++ v.C 还要考虑tunes.org情况

我知道constexpr关键字可用于在C ++中执行编译时计算。例如:

constexpr int factorial(int n)
{
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

(摘自https://en.cppreference.com/w/cpp/language/constexpr

可以将编译时计算视为C ++ v。C的主要优势吗?

据我了解,在C语言中无法进行编译时计算。constexpr不可用,我认为必须在运行时对代码进行评估。

与同等的C程序相比,C ++程序是否可以通过这种方式获得更好的性能(例如速度)?

解决方法

只有一件事是确定的-编译时计算使C ++编译器变得更加复杂,而编译速度变得更慢,因为在编译期间需要编译器执行此操作;例如查看

constexpr int factorial(int n) {
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void) {
    static_assert(factorial(10) == 3628800,"factorial 10 was correct");
    static_assert(factorial(3) == 42,"factorial 3 was 42");
}

由于后期 static_assert而不是编译必不可少。


C编译器不需要这种复杂性,因为不要求C编译器必须能够在编译期间计算递归函数的值。一个简单的C编译器可以很好地将每个 statement 分别汇编为机器代码,而不必记住前面的语句做了什么。 C标准当然不要求它能够在编译期间评估递归函数。

但这并不是说在编译期间没有C编译器会这样做。参见以下示例:

#include <stdio.h>

int factorial(int n) {
    return n <= 1 ? 1 : (n * factorial(n - 1));
}

int main(void) {
    printf("%d\n",factorial(10));
}

Compiled with GCC 10.2 as a C program with -O3,感谢the as-if rule,该程序成为了

factorial:
        mov     eax,1
        cmp     edi,1
        jle     .L4
.L3:
        mov     edx,edi
        sub     edi,1
        imul    eax,edx
        cmp     edi,1
        jne     .L3
        ret
.L4:
        ret
.LC0:
        .string "%d\n"
main:
        sub     rsp,8
        mov     esi,3628800
        mov     edi,OFFSET FLAT:.LC0
        xor     eax,eax
        call    printf
        xor     eax,eax
        add     rsp,8
        ret

更直接对应的

unsigned factorial(unsigned n) {
     unsigned i = 1;
     while (n > 1) {
         i *= n;
         n --;
     }
     return i;
}

int main(void) {
    printf("%d\n",3628800);
}

即编译器不仅将递归简化为一个简单的while循环,而且还解析了常量的阶乘,而且都没有任何特殊的关键字。

,

可以将编译时计算视为C ++ v。C的主要优势吗?

实际上,重要的不是编译,而是software building

请参阅build automation上的Wikipedia页面。

然后,请注意许多软件项目(包括githubgitlab上的许多开源项目)正在生成 C (甚至C ++)来自更抽象的内容的代码(例如,使用软件工具)。一个典型的例子显然是解析器生成器(也称为compiler-compilers),例如GNU bisonANTLR。另一个示例是粘合代码生成器,例如rpcgenSWIG。并且GNU autoconf使您的构建适应计算机上可用的软件包。请注意,Chicken-SchemeBigoo都从Scheme源代码生成C代码。当然请参见this。在某些情况下,巨大的C文件是通过微小的输入生成的(另请参见XBM格式)。 Maple能够生成大型C文件,并且在某些情况下会生成大量C代码-例如五百万行-很有道理(如Pitrat的书Artificial beings: the conscience of a conscious machine中所述)和blog

最后,whole-program optimization可以存在(请参见最新GCC中的Link-Time-Optimization-flto标志;您实际上将使用gcc -Wall -O2 -flto进行编译和link),并且在“链接时”需要一些编译器支持。

在某些情况下,编译时间并不那么重要(例如,编译FirefoxLinux kernelLibreOfficeGnomeGTK(从其源代码库中获取),但是构建时间可以持续数小时,或者甚至可以是数十分钟(因为有许多不同的translation units-具体来说,{{1} }或*.c文件-必须先进行编译然后链接)。

有传言称,Google内部会花费数小时的计算机时间来构建其大部分内部软件。

请注意,第一个C ++编译器(例如Cfront)已被实现为C代码生成器,并且大型软件(例如{{3 }}编译器有数十个专用的C或C ++代码生成器。尝试通过可用的源代码在笔记本电脑上构建针对您的GCC板的GCC交叉编译器(该板太小且功能不足,无法在其上直接编译GCC)。这样,在RaspBerryPi上的构建说明就有意义了。

有关生成C代码的C程序的示例,请参见我的LinuxFromScratch Linux版代码或manydl.c报告中描述的Bismon程序。过时的this draft项目的过去版本确实生成了一百万行C或C ++代码。 *.cc可以在几天内生成然后编译C代码,并说明GCC MELT可以被多次使用。有关在Linux上生成C ++的C ++软件的示例,请参见我的dlopen(3)项目。另请参阅RefPerSys,以获取与元编程和C或C ++代码生成有关的讨论。

还要考虑tunes.org情况

例如可能使用cross-compilation在笔记本电脑上为Arduino编译C代码或为RaspberryPi编译C ++代码。或在遥远的GCC超级计算机上编译您的PC代码。

关于C ++ top500 C

我对C ++标准versus的理解是,未在此处指定编译时计算(但我并不声称自己是C ++专家)。 特别是,没有什么禁止您编写C ++ n3337 (您可以在C,C ++,Ocaml,Java等语言中进行编码)。将该想法视为有趣的编程练习(但请在尝试之前先阅读interpreter)。

我的观点是,按照C ++标准中的规定,学习C ++的学生课堂可以被视为C ++的实现。教授C ++的一种好方法是向教室询问几个C ++程序的Dragon book,可以用铅笔,纸或semantics来教。我实际上以这种方式(在巴黎第六大学)教过whiteboard的一门课程。 黑板是黑色的,我用了各种颜色的粉笔。

还查看诸如operational semanticsFrama-C之类的软件工具。两者均为Clang static analyzer,因此您可以研究其来源。

与同等的C程序相比,C ++程序是否可以通过这种方式获得更好的性能(例如速度)?

表示您的意见,并且我不同意。是什么让您认为,如果open sourceOcaml的运行时是用C ++编写的,它将更快(您应该下载并研究源代码)? 一个有趣的练习可能是使用SBCL编译器以C ++进行编码(对于C语言,针对Linux上的x86 32位和x86-64位,以C语言进行编码),然后对所有改进进行基准测试。那个简单而又聪明的编译器可以非常快速地编译C代码,但是却很少tinyCC

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-