C 是否返回内部,是否返回外部或内部?

C 是否返回内部,是否返回外部或内部?,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

(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;
    }
    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