'else if' 在这个函数中是多余的吗?
Is the 'else if' redundant in this function?
所以,在C程序中用下面的函数来判断一个数是质数还是合数:
/**
* Determine if a given integer is prime. O(sqrt n).
* n: The integer to examine.
* return: TRUE if n is prime; FALSE if n is not prime.
*/
BOOL APIENTRY IsPrime(int n)
{
int i;
double test;
if(n <= 1) return FALSE;
else if(n <= 3) return TRUE; // Is the else keyword at beginning of this line useful?
for(i = 2; i <= sqrt(n); i++)
{
test = (double) n / (double) i;
if (test == floor(test)) return FALSE;
}
return TRUE;
}
如果我用 if (n <= 3) return TRUE;
替换第 12 行,该函数仍然可以正常工作(因为前面的 if
语句捕获了 n 不是质数的情况,前提是它是 1, 0或负数)。不管怎样,我都应该保留 else
关键字吗?
if(n <= 1) return FALSE;
else if(n <= 3) return TRUE;
和
if(n <= 1) return FALSE;
if(n <= 3) return TRUE;
相同,因为 return FALSE;
结束当前函数的执行(与任何 return
语句一样)。所以生成的汇编代码应该是相同的,你可以保留或不保留它,因为你觉得更易读。
由你决定,真的。
此外,i
从2开始,所以是的,你可以丢弃它。
题外话:为什么要用浮点运算?你想找到质数。你可能会遇到问题,小心!
如果你的编译器足够聪明,在if
之前有或没有else
编译后的代码都是一样的。
但是,在您的代码中,您写道:
for (...; n<= sqrt(n); ...)
哪个可以(再次取决于编译器)在每次循环迭代时调用 sqrt
函数。
替换为:
int limit = sqrt(n);
for (i = 3; i <= limit; i +=2)
...
是的,if
分支无条件返回后的 else
总是多余的:
if (someCondition) {
... do something, then
return someValue;
} // <<== An "else" here would be redundant
... more code
到达"more code"行的唯一方法是someCondition
计算为false
,这与到达else
分支的条件相同。
if
分支与其他类型的无条件控制转移也是如此,例如break
和continue
。存在代码分析工具来警告程序员冗余。
在这种情况下,它是无关紧要的,因为您是在 return 编写代码。在这两种情况下,编译后的代码都会在 n > 1
时跳转到 if (n <= 3)
,无论如何。
这是因为如果第一个 if
语句为假,则必须始终评估第二个条件。这在两个函数的汇编器输出中很容易看出(并且应该始终直接验证):
Ltmp7:
cmpl , %edi
jge LBB0_2
xorl %eax, %eax
jmp LBB0_8 // jump to return false
LBB0_2:
movb , %r14b
cmpl , %edi
jl LBB0_3 // jump to return true
对
Ltmp15:
cmpl , %edi
jge LBB1_2
xorl %eax, %eax
jmp LBB1_8 // jump to return false
LBB1_2:
movb , %r14b
cmpl , %edi
jl LBB1_3 // jump to return true
将代码修改为类似
if (n <= 3) return n > 1;
因为现在你只有一个分支,所以它可以进行不同的优化,例如在我的编译器 (clang-3.4) 上它产生
cmpl , %edi
jge LBB0_1 // jump to function body
cmpl , %edi
setg %al
jmp LBB0_7 // jump to return with $al register already set
其中使用setg
指令直接根据前面的比较设置return值
所以,在C程序中用下面的函数来判断一个数是质数还是合数:
/**
* Determine if a given integer is prime. O(sqrt n).
* n: The integer to examine.
* return: TRUE if n is prime; FALSE if n is not prime.
*/
BOOL APIENTRY IsPrime(int n)
{
int i;
double test;
if(n <= 1) return FALSE;
else if(n <= 3) return TRUE; // Is the else keyword at beginning of this line useful?
for(i = 2; i <= sqrt(n); i++)
{
test = (double) n / (double) i;
if (test == floor(test)) return FALSE;
}
return TRUE;
}
如果我用 if (n <= 3) return TRUE;
替换第 12 行,该函数仍然可以正常工作(因为前面的 if
语句捕获了 n 不是质数的情况,前提是它是 1, 0或负数)。不管怎样,我都应该保留 else
关键字吗?
if(n <= 1) return FALSE;
else if(n <= 3) return TRUE;
和
if(n <= 1) return FALSE;
if(n <= 3) return TRUE;
相同,因为 return FALSE;
结束当前函数的执行(与任何 return
语句一样)。所以生成的汇编代码应该是相同的,你可以保留或不保留它,因为你觉得更易读。
由你决定,真的。
此外,i
从2开始,所以是的,你可以丢弃它。
题外话:为什么要用浮点运算?你想找到质数。你可能会遇到问题,小心!
如果你的编译器足够聪明,在if
之前有或没有else
编译后的代码都是一样的。
但是,在您的代码中,您写道:
for (...; n<= sqrt(n); ...)
哪个可以(再次取决于编译器)在每次循环迭代时调用 sqrt
函数。
替换为:
int limit = sqrt(n);
for (i = 3; i <= limit; i +=2)
...
是的,if
分支无条件返回后的 else
总是多余的:
if (someCondition) {
... do something, then
return someValue;
} // <<== An "else" here would be redundant
... more code
到达"more code"行的唯一方法是someCondition
计算为false
,这与到达else
分支的条件相同。
if
分支与其他类型的无条件控制转移也是如此,例如break
和continue
。存在代码分析工具来警告程序员冗余。
在这种情况下,它是无关紧要的,因为您是在 return 编写代码。在这两种情况下,编译后的代码都会在 n > 1
时跳转到 if (n <= 3)
,无论如何。
这是因为如果第一个 if
语句为假,则必须始终评估第二个条件。这在两个函数的汇编器输出中很容易看出(并且应该始终直接验证):
Ltmp7:
cmpl , %edi
jge LBB0_2
xorl %eax, %eax
jmp LBB0_8 // jump to return false
LBB0_2:
movb , %r14b
cmpl , %edi
jl LBB0_3 // jump to return true
对
Ltmp15:
cmpl , %edi
jge LBB1_2
xorl %eax, %eax
jmp LBB1_8 // jump to return false
LBB1_2:
movb , %r14b
cmpl , %edi
jl LBB1_3 // jump to return true
将代码修改为类似
if (n <= 3) return n > 1;
因为现在你只有一个分支,所以它可以进行不同的优化,例如在我的编译器 (clang-3.4) 上它产生
cmpl , %edi
jge LBB0_1 // jump to function body
cmpl , %edi
setg %al
jmp LBB0_7 // jump to return with $al register already set
其中使用setg
指令直接根据前面的比较设置return值