从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中是否可以传递(传统使用“传递”)?
答案 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