我不明白这意味着什么。如果我试着猜测我会说byValue参数传递就是当你根据变量的值传递一个参数时,所以我在想:
if (a == 1){
PassAnArgumentOrSomething()
}
然而,这可能是错误的:/
至于参考,我不知道。
如果有人能帮助我,那就太棒了:)
答案 0 :(得分:4)
除了数组和函数(见下文)之外,C总是传递`by value':每个参数的值的副本被传递给函数;该函数无法修改传递给它的实际参数:
void foo(int j) {
j = 0; /* modifies the copy of the argument received by the function */
}
int main(void) {
int k=10;
foo(k);
/* k still equals 10 */
}
如果你想要一个函数来修改它的参数,你可以使用指针参数获得所需的效果:
void foo(int *j) {
*j = 0;
}
int main(void) {
int k=10;
foo(&k);
/* k now equals 0 */
}
有时在其他语言中称为“通过引用传递”。
答案 1 :(得分:2)
没有通过引用传递c语言
按值传递:表示您正在创建变量的临时副本并发送到参数。
通过引用传递(c语言中没有这样的概念):意味着您在调用时只是为原始变量指定了另一个名称,并且没有创建变量的临时副本。
按值调用:
int foo(int temp)
{
/.../
}
int main()
{
int x;
foo(x); /* here a temporary copy of the 'x' is created and sent to the foo function.*/
}
通过引用调用(c语言中没有这样的概念)
int foo(int& temp)
{
/.../
}
int main()
{
int x;
foo(x); /* here no temporary copy of 'x' is being created rather the variable *temp* in the calling function is just another name of the variable a in the main function*/
}
答案 2 :(得分:1)
按值传递参数意味着您要传递副本:
void f(int x)
{
x = 7;
// x is 7 here, but we only changed our local copy
}
void g()
{
int y = 3;
f(y);
// y is still 3 here!
}
通过引用传递参数意味着您没有传递副本,而是通过某种方式引用原始变量。在C中,所有参数都是按值传递的,但通常用来获得与通过引用传递相同的效果的方法是传递指针:
void f(int *x_ptr) { *x_ptr = 7; }
void g()
{
int y = 3;
f(&y);
// y is 7 here
}
以这样的方式传递数组,使其看起来类似于传递引用,但实际发生的事情更复杂。例如:
void f(int a[]) { a[0] = 7; }
void g()
{
int b[3] = {1,2,3};
f(b);
// b[0] is 7 here! looks like it was passed by reference.
}
这里实际发生的是数组b
被隐式转换为指向第一个元素的指针(这称为衰变)。 int a[]
参数的f
表示法实际上是指针的语法糖。上面的代码相当于:
void f(int *a) { a[0] = 7; }
void g()
{
int b[3] = {1,2,3};
f(&b[0]);
// b[0] is 7 here
}
答案 3 :(得分:0)
按值传递值是传递值本身;它会复制该值,并且您在新函数中所做的任何更改都不会保存到原始变量中:
void foo(int num)
{
num = 5; // Does not save to the original variable that was passed when foo was called
...
}
通过引用传递传递变量的位置;它允许新函数直接编辑原始变量:
void bar(int * num)
{
*num = 5; // Changes the variable in the original function
...
}
答案 4 :(得分:0)
每当程序加载时,它会得到一个所谓的地址空间的内存区域,它被分成不同的区域
考虑一个如此定义的函数
void doSomething(int x)
{
x++;
}//end of function
在另一个函数或主函数中被称为doSomething(5)或doSomething(y)。
这里 x 是用于“doSomething”功能的局部变量。它在堆栈区域的某处获得它的主页(内存位置)。
当doSomething(5)被称为 5 被复制到 x 的内存或doSomething(y)被称为 value / content y (不同的内存位置)会被复制到 x的内存。无论在 x 上应用什么操作,都不会影响 y 的内容/值。由于它的记忆位置不同。
每当执行流程到达功能结束时 x die /被销毁。无论x的值是什么,都无法访问/可用。简而言之,更新丢失且y不受影响(未反映变更)。
现在 考虑另一个如此定义的函数
void doSomething(int *x)
{
(*x)++;
}
被称为doSomething(& y)
这里 x 被称为指针(概念上称为引用*)。它也会在堆栈区域的某个地方回家
当doSomething(& y)被称为地址y 被复制到 x的位置块时。由于此 x 是特殊变量,因此称为指针,其中包含地址,并且据说 x表示/指向y 。
当应用(* x)++ 时,这里*是间接运算符,它将 x 引用 context 即ie。 (* x)++ 会间接地将y的值更改为1. x的值本身不会发生任何事情。
每当执行流程到达功能结束 * x死亡/被销毁时,正如预期的那样 更改 y (间接),它在堆栈区域的某处仍然存在(更改被反映)。
也不是这次doSomething(& 5)或doSomething(任何文字)不可能因为非法来获取任何文字的地址。
请注意,Call by Reference在C ++中具有另一种含义,但在概念上保持不变。
答案 5 :(得分:0)
让我们先看一下“调用”函数。
在C中,函数的参数通常是“按值”。下面,在致电sqrt(x)
后,x
的值sqrt()
未更改为x
的副本,因此永远无法获得能力影响x
。
y = sqrt(x);
// x did not change
printf("%f is the square root of %f\n", y, x);
函数的数组参数似乎是“通过引用”。调用fgets()
后,预计buf
会被更改。 fgets()
没有收到char
数组的副本,但是“引用”。因此fgets()
可能会影响数组的内容。
char buf[80] = { 0 }; // array 80 of char
printf("Before <%s>\n", buf); // "<>"
fgets(buf, sizeof buf, stdin);
printf("After <%s>\n", buf); // "<Hello World!>"
现在让我们来看看“接收”部分:功能。
类型double
,int
,struct
类型的函数参数按值接收。这里f
的值是上面x
的副本。对f
所做的任何更改都不会影响调用代码中的x
。
double sqrt(double f) {
double y;
... // lots of code
return y;
}
现在是棘手的一点,这是C中有很多讨论的地方。
下面的s
中的参数fgets()
未分配上面的buf
(char的数组80),而是为s
分配了指针类型派生自buf
:buf
的第一个元素的地址。通过了解buf
(通过s
)数组元素的地址,fgets()
会影响上面打印的内容。
char *fgets(char * restrict s, int n, FILE * restrict stream) {
// code
s[i] = ThisAndThat();
// code
return s;
}
现在让我们看看如何调用fgets()
:
char *p = malloc(80);
*p = '\0';
printf("Before <%s>\n", p); // "<>"
fgets(p, 80, stdin);
printf("After <%s>\n", p); // "<Hello World!>"
在第二个例子中,p
是“指向char的指针”。它由值传递给fgets()
。 fgets()
已通过s
收到p
的副本。
中心思想:fgets()
如果收到“数组第一个元素的地址”或“指向char的指针”的副本,则不会知道。在这两种情况下,它都将s
视为“指向char的指针”。
我们假设fgets()
做了以下事情。在s
更改之前,它会影响s
指向的数据。然后s
指针改变了。 s
是本地变量,此分配不会更改调用例程变量buf
和p
。
char *fgets(char * restrict s, int n, FILE * restrict stream) {
// lots of code
s[0] = '\0';
// more code
s = NULL;
return s;
}
注意:还有其他问题,例如将函数作为参数传递,并在要考虑的结构中封装数组。