例如,假设我想使用函数初始化我的变量:
int x[10];
void init_x(){
for(int i=0; i<10; ++i){
x[i]=i*i;
}
}
它不一定是这个确切的函数,它可能更复杂并且在更大的数组或不同的int类型上完成,但无论如何,关键是结果是确定性的。我的问题是:它会更好(例如,我的程序每次都会更快地初始化),只是事先计算出这个结果并直接定义它吗?
int x[10]={0, 1, 4, 9, etc...}
这样,我只运行一次初始化函数(例如运行函数,然后将结果复制+粘贴到数组定义并注释掉代码),而不是每次打开程序时都是一次又一次。 (至少这是我的假设)
这样做有什么不利之处吗?
答案 0 :(得分:3)
如果我正确理解你的问题,你会问你是否可以在编译时而不是在运行时进行计算,是否有警告?
答案取决于计算的复杂程度。如果它们很简单(如你所说的那样确定),你通常可以成功地做到这一点。需要注意的是,进行计算的代码可能不易于阅读,并且可以大大增加编译时间。
这种技术的推广称为meta-programming,您可以在通常的代码之前添加一个额外级别的代码转换(编译) - &gt;二元转换。
您可以使用预处理器执行有限形式的操作。 GCC还支持一些静态评估的表达式。其他技术包括使用X-Macros基本上实现像C ++中的参数化模板。
有些库能够使用预处理器(P99 for instance)在编译时执行图灵完备计算。通常,语法是多毛的,有许多惯例,并且在生产之前需要学习许多习语。
与复杂的元编程相比,我在使用例如代码生成代码时,通过维护代码的同事获得了更高的代码清晰度和赞赏度。 Perl或Python脚本,而不是我与预处理器一起攻击的东西。
修改强>
通过一个例子来回答你的问题,我将告诉你,我专门为微控制器编写了大量的C代码,具有4-16kb RAM和16-128kb闪存代码空间。大多数应用程序至少存在十年,并且需要运行更新和功能添加。这意味着我必须小心谨慎,不要浪费资源,所以如果可以在编译时而不是在运行时计算某些东西,我总是更喜欢。这节省了代码空间,但代价是增加了构建系统的复杂性。 如果数据是恒定的,这也意味着我可以将它放在只读闪存中并节省宝贵的RAM。
另一个例子是aes-min project,它是AES128的一个小实现。我认为有一个构建选择,所以算法中的一个组件(S-box?)被预先计算并放入ROM而不是RAM。其他对称加密算法需要从密钥计算一些数据,如果密钥是静态的,则可以有效地使用这种预计算技术。
答案 1 :(得分:2)
在其他条件相同的情况下,人力的努力比cpu时间或磁盘空间更昂贵。做任何事情都需要最少的前期和持续的人力。制作复杂的多阶段构建过程可能会节省一点cpu或磁盘,但这会花费很多精力。
答案 2 :(得分:2)
正如其他人所提到的,这取决于生成相关变量所需的时间。如果需要大量的运行时间,那么预先计算它就有意义了。
这是一个如何做到这一点的例子:
genx.c(预先计算数组的程序):
#include <stdio.h>
int main()
{
int i;
printf("int x[] = {");
for(i=0; i<10; ++i){
if (i) printf(",");
printf(" %d", i*i);
}
printf(" };\n");
return 0;
}
运行时,输出:
int x[] = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 };
makefile:
CFLAGS=-Wall -Wextra
app: app.c x.c
gcc $(CFLAGS) -o app app.c
x.c: genx
./genx > x.c
genx: genx.c
gcc $(CFLAGS) -o genx genx.c
clean:
rm -f app genx x.c
app.c(应用程序文件):
#include <stdio.h>
#include "x.c"
int main()
{
int i;
for (i=0;i<10;i++) {
printf("x[%d]=%d\n",i,x[i]);
}
return 0;
}
当您运行make app
时,它会看到x.c
是一个依赖项,并首先运行该目标。 x.c
目标是通过运行genx
构建的,genx
本身是由genx.c
目标编译的。
假设x.c
没有变化,app
只会构建一次,并且必要时会包含其内容。
x[0]=0
x[1]=1
x[2]=4
x[3]=9
x[4]=16
x[5]=25
x[6]=36
x[7]=49
x[8]=64
x[9]=81
的输出:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
答案 3 :(得分:1)
初始化的数组必须存储在可执行文件中并从磁盘加载。如果计算很简单,那么处理器可以比从磁盘读取数据更快地完成计算。 这意味着将初始化数据放在可执行文件中可能会导致膨胀的可执行文件开始变慢,这是一种双输的情况。
答案 4 :(得分:0)
我的问题是:它会更好(例如,我的程序每次都会更快地初始化),只是事先计算出这个结果并直接定义它吗?
肯定会更快。它是否足够重要,取决于计算的复杂程度以及初始化变量的频率。
如果您决定使用硬编码数字初始化数组,我强烈建议您在评论中添加注释或代码,以解释您如何获得数字。否则,这将是一个维护问题。
这样做有什么不利之处吗?
我不会对这些数字进行硬编码,除非有支持证据证明通过这样做可以节省大量资金。