2013-01-04 77 views
3

我正在为我的一些C库工作C语言技能。在完成第一个工作实现之后,我现在将通过代码来使其更高效。目前,我正在通过引用或值传递函数参数的主题。为什么我会按C中的值传递函数参数?

我的问题是,为什么我会通过C中的值传递任何函数参数?代码可能看起来更清晰,但是不会总比通过引用传递效率更低?

+11

**每个**参数都通过C中的值传递。如果它不大于指针,传递一个副本肯定不是那么低效。 –

+0

更不用说这会是多么不方便:'int get_int(); void process_int_A(const int x); void process_int_B(const int * const x);'。比较:'void foo(){process_int_A(get_int()); }'''void foo(){const int result = get_int(); process_int_A(结果); }'。为每个返回值需要明确的中间存储将是杀手。在C++中这不是一个问题,在那里你可以绑定到临时值的“真实”引用。 – GManNickG

回答

5

在C中,所有参数都是按值传递的。一个真正的通过引用传递的是当你看到一个修改的,没有任何明确的间接所有的效果:使用值,而不是指针虽然

void f(int c, int *p) { 
    c++; // in C you can't change the original paramenter passed like this 
    p++; // or this 
} 

,常常需要:

int sum(int a, int b) { 
    return a + b; 
} 

你不会写如:

int sum(int *a, int *b) { 
    return *a + *b; 
} 

因为它不安全,效率低下。效率低下,因为存在额外的间接性。而且,在C中,指针参数表明调用者将通过指针修改该值(特别是当指针类型的大小小于或等于指针本身时)。

+0

这可能是一个愚蠢的问题,但为什么是'''int sum(int * a,int * b){return * a + * b; }'''函数不安全? – c00kiemonster

+0

,因为那样你就有了间接指向NULL /悬空指针的风险。 – perreal

+3

调用者现在需要为a和b创建变量,不能传递常量。调用者还必须决定是否需要'malloc'值或传递变量的地址,并假定值可能会被修改,因为它们不是'const'(可能需要复制值)。如果调用者传递NULL,未初始化的指针和/或指向无效内存位置的指针,则取消引用指针也不安全。 – Joe

1

请参阅Passing by reference in C。按引用传递是C中的一个用词不当,它指的是传递变量的地址而不是变量,但是您将指针传递给值为的变量。这就是说,如果你要将变量作为指针传递,那么是的,它会稍微更有效率,但主要原因是能够修改它指向的原始变量。如果您不希望这样做,建议您以价值为目的,以明确您的意图。

当然,就Cs较重的数据结构之一而言,所有这些都没有意义。无论你喜不喜欢,数组都通过指向第一个变量的指针传递。

+3

感谢**所有**信息**。 – Joe

0

两个原因:

  1. 很多时候,你将不得不取消引用您在很多时候已经通过指针(认为长for循环)。你不想每次都想取消引用那个地址的值。直接访问速度更快。

  2. 有时候你想修改函数内部的传入值,但不是调用者。例如:

    void foo(int count){ 
        while (count>0){ 
         printf("%d\n",count); 
         count--; 
        } 
    } 
    

如果你想要做上述的东西按引用传递,你会haev创建自己的函数中另一个变量来存储它第一次。

+0

取消引用变量与直接访问的性能损失是多少?它是在数量级的土地? – c00kiemonster

+0

它可以是3个周期而不是1个周期。如果您正在编写一个四核机器,谁在乎(主要)?如果你正在构建任何基于性能的(实时应用程序,嵌入式系统),这可能会产生巨大的差异。 – Phonon

+0

个人资料,个人资料,个人资料!这个答案的第一部分非常具有推测性,并且不考虑编译器优化。 – Dan

5

因为代码为计算机编写下一代人并不重要。如果您传递引用,则任何读者都必须假定任何调用的函数都可以更改其参数的值,并且在调用之前有义务检查它或复制参数。

你的函数签名是一个合约,并将你的代码分开,这样你就不必将整个代码库放入头部,以便理解某些领域正在发生什么,通过传递引用你正在做的下一个人的生活变得更糟,作为程序员的最大的工作应该是让下一个人的生活变得更好 - 因为下一个人可能会成为你。

+1

很好的答案。另外,传递值实际上可以更快,因为编译器知道参数不会互相混淆,因此可能会生成更好的代码。 – Nemo

+0

“让下一个人的生活变得更糟”的例子是一个很好的例子,这是我忽略的。 – c00kiemonster

+0

我一直认为下一个家伙是一个知道你地址的杀人狂。 –

相关问题