C 是否返回内部,是否返回外部或内部?
(C) 如果我有一个函数,它包含一个If,如果条件为true,那么它可以返回一个特定的值,而else则返回一个不同的值。使用else的效率是高还是低 i、 eC 是否返回内部,是否返回外部或内部?,c,optimization,if-statement,C,Optimization,If Statement,(C) 如果我有一个函数,它包含一个If,如果条件为true,那么它可以返回一个特定的值,而else则返回一个不同的值。使用else的效率是高还是低 i、 e int foo (int a) { if ((a > 0) && (a < SOME_LIMIT)) { b = a //maybe b is some global or something return 0; } else { return 1
int foo (int a) {
if ((a > 0) && (a < SOME_LIMIT)) {
b = a //maybe b is some global or something
return 0;
} else {
return 1;
}
return 0;
}
intfoo(inta){
如果((a>0)和((a<某个极限)){
b=a//也许b是全局的或其他的
返回0;
}否则{
返回1;
}
返回0;
}
或者只是
int foo (int a) {
if ((a > 0) && (a < SOME_LIMIT)) {
b = a //maybe b is some global or something
return 0;
}
return 1;
}
intfoo(inta){
如果((a>0)和((a<某个极限)){
b=a//也许b是全局的或其他的
返回0;
}
返回1;
}
假设GCC,第一个实现会导致编译代码与第二个不同吗
我需要在这里尽可能地提高效率,因此可能减少else的一个分支会很好——但从风格上讲,我内心的OCD不希望看到返回值不是0或void作为函数中的最后一条指令,因为它不太清楚发生了什么。因此,如果无论如何都要删除它,那么我可以将else留在那里…在两个实现之间检查对象文件。放置一个程序集标题,如
PortionInQuestion:
然后,它将作为标签显示在部件文件中,您可以看到生成的部件是如何不同的。它们可能完全不同(因为优化),也可能完全不同。如果没有看到原始程序集,就无法知道编译器是如何优化它的 您将无法到达最后一个
返回0第一个示例中的代码>。我想说,你的第二个是风格更清楚,至少因为这一点。为同一件事编写更少的代码通常是一件好事
关于性能,如果您喜欢这样的事情,您可以检查程序集可执行文件,或者分析代码,看看是否有实际的差异。我打赌没什么要紧的
最后,如果编译器支持优化标志,请使用它们 当然,这取决于编译器。我想市场上每一个(体面的)编译器在这两种情况下都会产生完全相同的输出。然而,任何关于优化的书都不鼓励尝试这种微观优化
选择可读性更好的表格。我会这样写
int foo (int a) {
if ((a > 0) && (a < SOME_LIMIT)) {
b = a //maybe b is some global or something
return 0;
} else {
return 1;
}
}
intfoo(inta){
如果((a>0)和((a<某个极限)){
b=a//也许b是全局的或其他的
返回0;
}否则{
返回1;
}
}
整个函数只是一个布尔函数,用于将b的值设置为大于零且小于某个常数。if语句对返回设置条件。无需向函数添加默认返回。默认返回将使if条件无效。您可以使用-O3-S
选项运行gcc来生成优化的程序集代码,以便查看(并比较)优化的程序集。我对您的源代码进行了以下更改,以使它们能够编译
文件a.c:
int b;
int foo (int a) {
if ((a > 0) && (a < 5000)) {
b = a;
return 0;
} else {
return 1;
}
return 0;
}
int b;
int foo (int a) {
if ((a > 0) && (a < 5000)) {
b = a;
return 0;
}
return 1;
}
使用gcc-O3-sb.c
编译b.c时,将创建文件b.S。在我的机器上,它看起来像这样:
.file "b.c"
.text
.p2align 4,,15
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
movl 4(%esp), %edx
movl $1, %eax
leal -1(%edx), %ecx
cmpl $4998, %ecx
ja .L2
movl %edx, b
xorb %al, %al
.L2:
rep
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.comm b,4,4
.ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
.section .note.GNU-stack,"",@progbits
请注意,foo:
的组合实现是相同的。因此,在本例中,使用此版本的GCC,您以何种方式编写代码并不重要。请尝试两种方式。赛马。在第一个实现中,由于if
和else
都有一个return
语句,因此最终的return
语句将永远不会到达。bool c=0将是我的最爱。它应该可以在一行中实现:返回((a>0)和&(a但即使它能工作,也不清楚。如果((未签名)(a-1)
是一个很好的微优化,如果您的编译器还没有这样做的话。但正如其他人所说,每个编译器都是不同的,所以如果你真的在意的话,没有什么可以替代查看程序集输出和/或分析。我不知道这是不鼓励的!每次学习新的东西;)“不要过早地优化”这个词与“不要过早地悲观”一起使用!(我没有做这些,你可以找到C++上的标准,高效C++和我想象的,在很多其他的书上的那些精确的表达式)哇,谢谢!我对编译器选项不太了解(我大部分时间都是在IDE上工作),所以我非常感激,因为我花了好几个小时来研究如何做到这一点,希望我能多次投票!
int foo (int a) {
/* Nothing to do: get out of here */
if (a <= 0 || a >= SOME_LIMIT) return 1;
b = a; // maybe b is some global or something
return 0;
}
int foo (int a) {
/* Nothing to do: get out of here */
if (a <= 0 || a >= SOME_LIMIT) return 1;
b = a; // maybe b is some global or something
return 0;
}
.file "return.c"
.text
.p2align 4,,15
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
leal -1(%rdi), %edx
movl $1, %eax
cmpl $2998, %edx
ja .L2
movl %edi, b(%rip)
xorb %al, %al
.L2:
rep
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.globl b
.bss
.align 16
.type b, @object
.size b, 4
b:
.zero 4
.ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
.section .note.GNU-stack,"",@progbits