Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.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_Loops_Model Checking - Fatal编程技术网

C 如何在源代码级别自动展开源代码中的循环?

C 如何在源代码级别自动展开源代码中的循环?,c,loops,model-checking,C,Loops,Model Checking,我想在源代码级别自动解开用C编写的目标程序中的循环(仅供参考,我使用linux和gcc编译器)。 关于详细的描述,让我们看看下面的简单源代码 1: int main(){ 2: int i = 0; 3: while(i<3){ 4: printf("hi\n"); 5: i++; 6: } 7: } 1:int main(){ 2:inti=0; 3:while(i循环展开只是GCC完成的一个(在许多优化中)优化(至少是-O2或-O3),它本身没有意义(它只

我想在源代码级别自动解开用C编写的目标程序中的循环(仅供参考,我使用linux和gcc编译器)。 关于详细的描述,让我们看看下面的简单源代码

1: int main(){
2:   int i = 0;
3:   while(i<3){
4:     printf("hi\n");
5:     i++;
6:   }
7: }
1:int main(){
2:inti=0;

3:while(i循环展开只是GCC完成的一个(在许多优化中)优化(至少是
-O2
-O3
),它本身没有意义(它只有通过其他优化才有帮助,比如不断传播)

当然,您不能只想要一个源代码(想象一下,对于展开循环的
循环,许多宏可能被扩展为

我建议您扩展GCC编译器,例如,它是扩展GCC的高级领域特定语言

(或者,如果你有很多时间,用C痛苦地编写你的GCC插件)

然后,您将在一些循环展开(和其他优化)过程之后添加一个过程,该过程将处理Gimple的内部表示(您可以将Gimple理解为一种类似“最小”C语言,只进行基本操作,如la
x=y+z;
和调用以及简单测试,如
if(x>y)goto l;


但我仍然不明白你想对结果做什么。如果你想进一步分析它,请在编译器内部处理(可能是用MELT编码的另一个过程)GCC内部表示。如果你想提供“展开的”编写一些外部工具的代码,编写一个转换过程,将Gimple转换为适当的格式。

您应该查看汇编程序,了解编译器在循环展开中的实际性能。但您也可以帮助编译器更好地编程:

for (unsigned i = 0; i < 3; ++i) {
  printf("hi\n");
}
for(无符号i=0;i<3;++i){
printf(“hi\n”);
}
也就是说,使用无符号整数类型作为循环变量(
size\t
通常是个好主意),并将循环变量设置为本地变量。然后使用类似于
-S-O3-march=native的编译器选项检查汇编程序


然后,也只有到那时,如果您对结果不满意,请查看。它有一组宏来进行展开,而不仅仅是循环。查找类似于
P99_for
的内容几乎总是,在确定某些代码是否适合展开代码方面,gcc会比您做得更好。根据我的经验,这是极为罕见的您可以比gcc做得更好—唯一合理的情况是当您有非常复杂的代码执行“奇怪”的事情时,您的示例中肯定不是这样

您是否确实尝试过在优化中使用-S选项来查看编译器的功能


当然,编译器可能有不优化这个特定循环的感觉,因为printf()比所有循环加在一起要重得多——但这是一个稍微不同的问题。

编译器已经在这样做了……对于您的示例,它可能只会得到三个
printf(“hi\n”)实例
没有任何剩余的测试或增量的
i
你到底为什么要问?你想对输出做什么?为什么你需要它成为一些“源代码”?你正在将它输入另一个工具吗?哪一个?谢谢你的回答。顺便问一句,有没有一种方法可以在所有循环都不需要的情况下获得源代码?这是我的问题:)转换源代码的覆盖率将通过出于某种目的使用Gcov来衡量。我不理解你的问题。你似乎错误地认为编译器正在转换源代码;事实并非如此。它正在将源代码解析为一些内部表示,并将内部表示转换为其他表示。选项
 -fdump tree all
(和其他类似选项)生成数百个转储文件,显示编译各个阶段内部GCC表示的文本形式。
1: void ex(int i){
2:   int i = 0;
3:   while(i<3){
4:     printf("hi\n");
5:     i++;
6:   }
7: }
1: void ex(int i){
2:   if (i<3){
3:     printf("hi\n");
4:     i++;
5:   }
6:   if (i<3){
7:     printf("hi\n");
8:     i++;
9:   }
10:  if (i<3){
11:    printf("hi\n");
12:    i++;
13:  }
14:}
for (unsigned i = 0; i < 3; ++i) {
  printf("hi\n");
}