可以公平地说,当传递给C中的函数时,所有参数或参数都被复制了吗?

时间:2018-04-04 05:42:32

标签: c

Why does scanf() require &?开始,提到

  

C中的所有参数都是按值传递的。

void change( int * var ) {
    // Here, var is a pointer to the original number. var == &value
    // Writing to `*var` modifies the variable the pointer points to
    *var = 1337;
}

我可以写一下

void change( int * var ) {
    // Here, var is a copy of a pointer that happens to point to the same memory block as the original pointer. var == &value
    // Writing to `*var` modifies the variable the pointer points to
    *var = 1337;
}

假设

int main() {
    int value = 42;
    change(&value);
    return 0;
}

无法在C中传递任何内容是使用“pass”的传统含义的正确语句。我的理解是否合理?

我的问题是:C中是否可以传递(传统使用“传递”)?

2 个答案:

答案 0 :(得分:2)

是的,C中的所有*都是按值传递的,这意味着参数的副本会传递给函数 - 这是将值传递给函数的唯一方法。 “通过指针”(或“引用”)并不存在 - 它仍然是“通过值传递”,其中“值”是指针。指尖毕竟是价值观。

语言说明当我们说“你能给我一些糖吗”我们希望有人暂时将糖碗转让给我们,所以在任何时候时间只有一个糖碗。换句话说,我们希望糖碗能够移动给我们。在编程中并非如此。在此上下文中“传递”仅意味着“将参数与被调用的函数相关联”,并且不一定涉及移动。这就是为什么我们区分“按值传递”,“按引用传递”,“按名称传递”等。

示例:

/* I have 2 apples, 3 oranges and one pear */
int apple = 2;
int orange = 3;
int pear = 1;

/* Apples are my favorite fruit */
int *my_favorite_fruit = &apple;

void no_eat_fruit (int fruit) {
    /* Does not work, "fruit" is copy, so changes to it have no effect outside function */
    fruit--;
}
no_eat_fruit(apple);
/* No apples have been eaten at this point */


void eat_fruit(int *fruit) {
    /* Here, "fruit" is copy, but "*fruit" refers to original object */
    *fruit--;
}
eat_fruit(&apple);
eat_fruit(my_favorite_fruit);
/* I have no apples left */

/* Let's change my mind, now I like oranges */

void no_change_my_mind(int *favorite) {
    /* Doesn't work, "favorite" is copy, so changes to it have no effect outside function */
    favorite = &orange;
}
no_change_my_mind(my_favorite_fruit);
/* I still like apples, LOL! */

void change_my_mind(int **favorite) {
    /* In order to change pointer, we have pass pointer-to-pointer.
       Here, "favorite" is copy, but "*favorite" points to original pointer */
    *favorite = &orange;
}
change_my_mind(&my_favorite_fruit);

*,但数组除外。传递给函数时,数组为“decay into pointers”。

答案 1 :(得分:0)

这个问题一直绞尽脑汁。我必须证明这一点。出于对el.pescado的努力的尊重,我将他或她的回答作为公认的答案。

代码

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


void copy( int * memoryslot )
{
  /* This does not prove that * memoryslot is a copied pointer */
  printf("copy:              ValueCopied:        %p\n", memoryslot);  /* memoryslot is a ptr    */
  printf("copy: CalculatedPointerAddress:        %p <- Well, it is not. Here is the proof.\n", &memoryslot); /* get address of pointer */
  * memoryslot = 30; /* To prove I can still use a copy to change the original value */
  return;
}

int main(void) 
{
  int memoryslot = 20;
  int * memoryslotPtr = &memoryslot;
  printf("Caller                 Pointer to memory slot\n");
  printf("-------------------------------------\n");
  printf("main:                    Value:        %d\n", memoryslot);
  printf("main:   CalculatedValueAddress:        %p\n", &memoryslot);
  printf("main: CalculatedPointerAddress:        %p <- If * memoryslot were the same, it would be this.\n", &memoryslotPtr);

  /* Pass address, yields same as &memoryslot */
  copy( memoryslotPtr ); 

  printf("main:                    Value:        %d\n", memoryslot);


  return EXIT_SUCCESS;
}

输出

Caller                 Pointer to memory slot
-------------------------------------
main:                    Value:        20
main:   CalculatedValueAddress:        0x7ffee9134c48
main: CalculatedPointerAddress:        0x7ffee9134c40 <- If * memoryslot were the same, it would be this.
copy:              ValueCopied:        0x7ffee9134c48
copy: CalculatedPointerAddress:        0x7ffee9134c08 <- Well, it is not. Here is the proof.
main:                    Value:        30