0

假设我有一个取决于条件的变量。从效率的角度来看,我应该使用

int s;
if (d > 2)
{
   s = -1;
}
else
{
   s = 1;
}

要不就

int s = 1;
if (d > 2)
{
   s = -1;
}

有人可以解释其中的区别吗?编译语言(例如 C)与解释语言(例如 Python)之间有什么区别吗?

请注意,这个问题与我之前的一个问题有关,我问的原因是一样的:它在任何编程语言中都非常频繁,我最终总是问自己应该使用什么。

4

7 回答 7

1

看来,这不是性能问题。大多数编译器都会产生相同的代码,如果它们不产生,那应该不会对性能产生任何明显的影响。除非您在每个 CPU 周期都很重要的非常(非常)紧凑的环境中工作。这不应该是这样,除非你是一个从七十年代刚到的时间旅行者......

更严重的是,正如在各种评论中多次注意到的那样,这更多的是可读性沟通问题。在那之后,很难说一种形式比另一种更好

个人的习惯是,if ... else ...当我想强调程序中显然有两条不同的“权重”相同的路径时使用。set to default; if ...当我想说“嗯,这if是一个特例”时,我会使用另一种选择。

由于这与您的另一个问题有关,您可能会将没有 else的表单视为某种保护条款,例如if ... return ...; return ...

于 2013-06-19T10:14:29.347 回答
1

如果你真的有大量这样的代码,你正在初始化1or -1,并且它真的运行了很多次,所以它会影响性能,你可以使用无分支版本:

int s = 1 - 2*(d > 2);

更一般地,您可以为初始化值设置一个数组:

const int s_ini[2] = { 1, -1 };
int s = s_ini[d > 2];
于 2013-06-19T08:09:40.940 回答
1

没有区别,通过优化gcc -S -O2你给出相同的输出:

    .file   "demo.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "%d"
    .section    .text.startup,"ax",@progbits
    .p2align 4,,15
    .globl  main
    .type   main, @function
main:
.LFB11:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $-1, %esi
    movl    $.LC0, %edi
    xorl    %eax, %eax
    call    printf
    xorl    %eax, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE11:
    .size   main, .-main
    .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
    .section    .note.GNU-stack,"",@progbits
于 2013-06-19T07:57:38.787 回答
1

这是我个人更喜欢(有时是可怕的)三元运算符的情况?:,如下所示:

const int s = (d < 2) ? -1 : 1;

自从:

  1. 这允许s成为const,在我看来这是一个巨大的胜利。当然,这假设变量仅在初始化后才被读取。
  2. 它(像其他解决方案一样)只写入s一次,这可以更快。

我通过计算避免了“聪明的技巧”。

于 2013-06-19T09:01:07.860 回答
0

性能差异并不重要,但您的第一个符号对于其他程序员来说是最清楚的。

int s;
if (d > 2)
   s = -1;
else
   s = 1;

当程序员将 se "int s = 1;" 他可能不明白为什么您将这个变量初始化为 1,因为在两法分之后将其设置为 -1。

于 2013-06-19T07:57:16.597 回答
0

从代码的可读性来看,我觉得前者更好。如果您想获得更好的性能,我认为您可以按照@jxh 的回答进行操作。

于 2013-06-19T08:44:24.117 回答
0

在这种情况下,没有对错之分。这取决于。我相信即使运行时间可能有细微差别,你也应该总是更喜欢代码的可维护性。

在这种情况下,默认值更好,因为您必须通过所有条件才能成功返回。

    int rc = FAIL;

    /* do something */

    if (some-cond)
        goto end;

    /* do something */

    if (some-cond)
        goto end;

    rc = SUCCESS;

end:
    /* clean-up */
    return rc;
于 2013-06-19T08:01:11.623 回答