假设我有一个取决于条件的变量。从效率的角度来看,我应该使用
int s;
if (d > 2)
{
s = -1;
}
else
{
s = 1;
}
要不就
int s = 1;
if (d > 2)
{
s = -1;
}
有人可以解释其中的区别吗?编译语言(例如 C)与解释语言(例如 Python)之间有什么区别吗?
请注意,这个问题与我之前的一个问题有关,我问的原因是一样的:它在任何编程语言中都非常频繁,我最终总是问自己应该使用什么。
假设我有一个取决于条件的变量。从效率的角度来看,我应该使用
int s;
if (d > 2)
{
s = -1;
}
else
{
s = 1;
}
要不就
int s = 1;
if (d > 2)
{
s = -1;
}
有人可以解释其中的区别吗?编译语言(例如 C)与解释语言(例如 Python)之间有什么区别吗?
请注意,这个问题与我之前的一个问题有关,我问的原因是一样的:它在任何编程语言中都非常频繁,我最终总是问自己应该使用什么。
在我看来,这不是性能问题。大多数编译器都会产生相同的代码,如果它们不产生,那应该不会对性能产生任何明显的影响。除非您在每个 CPU 周期都很重要的非常(非常)紧凑的环境中工作。这不应该是这样,除非你是一个从七十年代刚到的时间旅行者......
更严重的是,正如在各种评论中多次注意到的那样,这更多的是可读性和沟通问题。在那之后,很难说一种形式比另一种更好。
我个人的习惯是,if ... else ...
当我想强调程序中显然有两条不同的“权重”相同的路径时使用。set to default; if ...
当我想说“嗯,这if
是一个特例”时,我会使用另一种选择。
由于这与您的另一个问题有关,您可能会将没有 else的表单视为某种保护条款,例如if ... return ...; return ...
如果你真的有大量这样的代码,你正在初始化1
or -1
,并且它真的运行了很多次,所以它会影响性能,你可以使用无分支版本:
int s = 1 - 2*(d > 2);
更一般地,您可以为初始化值设置一个数组:
const int s_ini[2] = { 1, -1 };
int s = s_ini[d > 2];
没有区别,通过优化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
这是我个人更喜欢(有时是可怕的)三元运算符的情况?:
,如下所示:
const int s = (d < 2) ? -1 : 1;
自从:
s
成为const
,在我看来这是一个巨大的胜利。当然,这假设变量仅在初始化后才被读取。s
一次,这可以更快。我通过计算避免了“聪明的技巧”。
性能差异并不重要,但您的第一个符号对于其他程序员来说是最清楚的。
int s;
if (d > 2)
s = -1;
else
s = 1;
当程序员将 se "int s = 1;" 他可能不明白为什么您将这个变量初始化为 1,因为在两法分之后将其设置为 -1。
从代码的可读性来看,我觉得前者更好。如果您想获得更好的性能,我认为您可以按照@jxh 的回答进行操作。
在这种情况下,没有对错之分。这取决于。我相信即使运行时间可能有细微差别,你也应该总是更喜欢代码的可维护性。
在这种情况下,默认值更好,因为您必须通过所有条件才能成功返回。
int rc = FAIL;
/* do something */
if (some-cond)
goto end;
/* do something */
if (some-cond)
goto end;
rc = SUCCESS;
end:
/* clean-up */
return rc;