2014-03-12 65 views
0

(我不知道这样做的正确的术语为了执行搜索或给予适当的标题)函数调用作为参数传递给其他函数

我一直在想:这很重要(speedwise或如果使用函数调用来为另一个函数提供参数,则按大小编译)我可以看到不是这样做可以帮助代码可读性,但有时使用一堆局部变量变得乏味。

我的意思:假设这些被称为多次(如在for..loop)是有这个之间的任何实际差别:

 byte patternType = mCols[i].getPatternType(); 
     byte stepIndex = mCols[i].update(m); 
     byte patternValue = getPatternValue(patternType, stepIndex); 

这:

 byte patternValue = getPatternValue(mCols[i].getPatternType(), mCols[i].update(m)); 

回答

0

它并不真正的物。如果在开启优化的情况下进行编译,则编译器应在两种情况下发出相同的代码;但前者具有优势,即在关闭优化的情况下更容易进行调试。

我刚刚在我的覆盆子pi上试过这个,因为我手边没有arduino。

这是我y1.c:

#include <stdlib.h> 
#include <stdio.h> 

typedef signed char byte; 

struct something { 
    byte (*getPatternType)(); 
    byte (*update)(int i); 
}; 

int main(void) { 
    struct something mCols[20]; 
    int i; 
    int m=3; 

    for (i=0; i<20; i++) { 
      byte patternType=mCols[i].getPatternType(); 
      byte stepIndex=mCols[i].update(m); 
      byte patternValue=getPatternValue(patternType, stepIndex); 
      printf("%d\n", patternValue); 
    } 
    exit(0); 
} 

,这是y2.c:

#include <stdlib.h> 
#include <stdio.h> 

typedef signed char byte; 

struct something { 
    byte (*getPatternType)(); 
    byte (*update)(int i); 
}; 

int main(void) { 
    struct something mCols[20]; 
    int i; 
    int m=3; 

    for (i=0; i<20; i++) { 
      byte patternValue=getPatternValue(mCols[i].getPatternType(), mCols[i].update(m)); 
      printf("%d\n", patternValue); 
    } 
    exit(0); 
} 

然后:

[email protected]$ cc -O4 -S y1.c 
[email protected]$ cc -O4 -S y2.c 
[email protected]$ diff y1.s y2.s 
13c13 
<  .file "y1.c" 
--- 
>  .file "y2.c" 

正如你看到的,在汇编水平,唯一不同的是嵌入式源文件名。

我添加了一个printf,所以编译器不会只是优化一切。它没有,这是y1.s:

.arch armv6 
    .eabi_attribute 27, 3 
    .eabi_attribute 28, 1 
    .fpu vfp 
    .eabi_attribute 20, 1 
    .eabi_attribute 21, 1 
    .eabi_attribute 23, 3 
    .eabi_attribute 24, 1 
    .eabi_attribute 25, 1 
    .eabi_attribute 26, 2 
    .eabi_attribute 30, 2 
    .eabi_attribute 18, 4 
    .file "y1.c" 
    .section  .text.startup,"ax",%progbits 
    .align 2 
    .global main 
    .type main, %function 
main: 
    @ args = 0, pretend = 0, frame = 160 
    @ frame_needed = 0, uses_anonymous_args = 0 
    stmfd sp!, {r4, r5, r6, lr} 
    mov  r4, #0 
    sub  sp, sp, #160 
.L2: 
    add  r5, sp, #0 
    ldr  r3, [r5, r4]! 
    blx  r3 
    add  r4, r4, #8 
    ldr  r3, [r5, #4] 
    mov  r6, r0 
    mov  r0, #3 
    blx  r3 
    mov  r1, r0 
    mov  r0, r6 
    bl  getPatternValue 
    sxtb r1, r0 
    ldr  r0, .L5 
    bl  printf 
    cmp  r4, #160 
    bne  .L2 
    mov  r0, #0 
    bl  exit 
.L6: 
    .align 2 
.L5: 
    .word .LC0 
    .size main, .-main 
    .section  .rodata.str1.4,"aMS",%progbits,1 
    .align 2 
.LC0: 
    .ascii "%d\012\000" 
    .ident "GCC: (Debian 4.6.3-14+rpi1) 4.6.3" 
    .section  .note.GNU-stack,"",%progbits 

注编译器如何处理在循环:控制寄存器R 4是由结构(8)的尺寸增加,而不是由一个,并与160 ,而不是20,最后。这样可以节省数组索引通常需要的乘法,但调试器无法在循环中获取i的“真实”值。

+0

谢谢 - 我明白@ 25%,但足以知道现在不用担心它。主要是我想知道它是否具有Arduino的记忆力。我应该看看编译后的输出,看看它对我的代码有什么作用。 –

3

评估参数的顺序是未定义的。如果功能是纯粹的,这应该不重要,但如果它们有副作用,它可以。

+0

好抓!没有想到当我写我的答案。 –

0

一般建议:

专注于代码的清晰性和可读性,让编译器做的工作,并优化掉不必要的东西。不要试图超越你的编译器,它会比程序员在代码优化方面做的更好。

此外,请小心顺序评估和序列点建议pat。如果你写的代码足够清晰,强硬,你通常不需要关心这些事情。

相关问题