66

我正在查看一些 C 代码,并注意到它充满了围绕代码块的大括号,没有任何类型的控制结构。看一看:

//do some stuff . . .
fprintf(stderr, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);
{
    //a block! why not?
    char *tmp_argv[3];
    tmp_argv[0] = argv[0]; tmp_argv[1] = str; tmp_argv[2] = prefix;
    t = clock();
    fprintf(stderr, "[bwa_index] Convert nucleotide PAC to color PAC... ");
    bwa_pac2cspac(3, tmp_argv);
    fprintf(stderr, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);
}

为什么要在代码中插入这样的块?它充满了他们。有某种性能优势吗?一些神秘的C东西?为什么???

编辑:此代码来自BWA ,这是一个使用Burrows-Wheeler 变换将小序列与大参考序列对齐的生物信息学程序,以防你们中的任何人想知道。此代码示例与应用程序的功能并不特别相关。

4

9 回答 9

95

遗留代码需要 { } 才能进行声明

在 C89 中,你不能随便做int i;任何事情;声明仅在块的开头有效。

所以:

a = 1;
int i; /* error */
i = 2;

...无效,但是

a = 1
if (e) {
  int i;

...很好,就像一个普通的街区。

即使在声明变得有效(C99)块项目(S)之后,所产生的风格仍然存在,部分是由于惯性,部分是为了向后可移植性,也因为为新声明建立一个范围是有意义的。

于 2009-11-05T01:31:00.507 回答
41

范围变量。例如,变量tmp_argv只在大括号之间有效。

于 2009-11-05T01:28:20.793 回答
13

我最近发现的另一个用例是当您具有打开/关闭语义并且想要清楚地标记“内部”代码时:

f = fopen('file');
{
    // do stuff
}
fclose(f);

这可以很好地提醒您关闭/释放对象,并使代码更加简洁。

于 2009-11-05T13:41:24.593 回答
7

块是一个范围,它决定了变量的生命周期,以及它们对编译器的可见性。因此,当控制退出块时,在块内创建的变量就会消失。

当这些变量是具有构造函数和析构函数的类的实例时,它会非常方便。

但是,在您的示例中没有太多优势。

于 2009-11-05T01:30:31.460 回答
6

它正在创建一个范围。堆栈对象在超出范围时被销毁。看起来它正在做某种类型的输入,这意味着每个块都是他们想要计时的东西。但是,我没有看到任何作用域计时器对象,所以,是的,没有任何意义。

于 2009-11-05T01:28:02.260 回答
6

您在块内声明的变量是该块的本地变量。这样,您可以tmp_argv在代码的其他位置(如下)重新定义,而不会与这段代码冲突。

于 2009-11-05T01:28:57.687 回答
1

这就是全部吗?也许程序员正在tmp_argv代码中的其他地方使用。我想不出任何其他原因,因为andtmp_argv与大括号之外的任何东西都是分开的。{}

于 2009-11-05T01:30:19.107 回答
1

在这些情况下,我有时会使用块: - 本地化变量 - 或者更易于阅读......

于 2009-11-05T03:59:40.240 回答
-4

嗯 - 我可能在这里不在图表中,但我认为在这样的块内定义的局部变量在块外是无效的

于 2009-11-05T01:28:02.230 回答