C 编程 - 引用传递
在下面的 C 程序中,我不明白为什么在调用 foo 后 buf[0] = 'A' 。 foo 不是在进行值传递吗?
#include <stdio.h>
#include <stdlib.h>
void foo(char buf[])
{
buf[0] = 'A';
}
int main(int argc, char *argv[])
{
char buf[10];
buf[0] = 'B';
printf("before foo | buf[0] = %c\n", buf[0]);
foo(buf);
printf("after foo | buf[0] = %c\n", buf[0]);
system("PAUSE");
return 0;
}
输出:
before foo | buf[0] = 'B'
after foo | buf[0] = 'A'
In the C program below, I don't understand why buf[0] = 'A' after I call foo. Isn't foo doing pass-by-value?
#include <stdio.h>
#include <stdlib.h>
void foo(char buf[])
{
buf[0] = 'A';
}
int main(int argc, char *argv[])
{
char buf[10];
buf[0] = 'B';
printf("before foo | buf[0] = %c\n", buf[0]);
foo(buf);
printf("after foo | buf[0] = %c\n", buf[0]);
system("PAUSE");
return 0;
}
output:
before foo | buf[0] = 'B'
after foo | buf[0] = 'A'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
相同
与调用它时
foo(buf)
,您按值传递指针,因此会创建指针的副本。指针的副本指向与原始指针相同的对象(或者,在本例中,指向数组的初始元素)。
C 不具有按引用传递语义,而 C++ 具有按引用传递语义。 C 中的所有内容都是按值传递的。指针用于获取引用语义传递。
is the same as
When you call it,
foo(buf)
, you pass a pointer by value, so a copy of the pointer is made.The copy of the pointer points to the same object as the original pointer (or, in this case, to the initial element of the array).
C does not have pass by reference semantics in the sense that C++ has pass by reference semantics. Everything in C is passed by value. Pointers are used to get pass by reference semantics.
数组只是使用指针的一种奇特方式。当您将
buf
传递给函数时,您是按值传递指针,但是当您取消引用该指针时,您仍然引用它指向的字符串。an array is just a fancy way to use a pointer. When you pass
buf
to the function, you're passing a pointer by value, but when you dereference the pointer, you're still referencing the string it points to.数组作为函数参数相当于指针,因此声明
相同。
与数组参数衰减为指向其第一个元素的指针
Array as function parameter is equivalent to a pointer, so the declaration
is the same as
The array argument is then decayed to the pointer to its first element.
数组的处理方式与其他类型不同;您不能在 C 中“按值”传递数组。
在线 C99 标准(草案 n1256),第 6.3.2.1 节,“左值、数组和函数指示符”,第 3 段:
在调用中,
数组表达式
buf
不是sizeof
或&
的操作数,也不是用于初始化数组的字符串文字,因此它从类型“10 元素 char 数组”隐式转换(“衰减”)为“指向 char 的指针”,并且第一个元素的地址被传递给 foo。因此,您对foo()
中的buf
所做的任何操作都将反映在main()
中的buf
数组中。由于数组下标的定义方式,您可以在指针类型上使用下标运算符,因此它看起来就像您正在使用数组类型,但实际上并非如此。在函数参数声明的上下文中,
T a[]
和T a[N]
与T *a
同义,但这是仅在这种情况下才是正确的。Arrays are treated differently than other types; you cannot pass an array "by value" in C.
Online C99 standard (draft n1256), section 6.3.2.1, "Lvalues, arrays, and function designators", paragraph 3:
In the call
the array expression
buf
is not the operand ofsizeof
or&
, nor is it a string literal being used to initialize an array, so it is implicitly converted ("decays") from type "10-element array of char" to "pointer to char", and the address of the first element is passed to foo. Therefore, anything you do tobuf
infoo()
will be reflected in thebuf
array inmain()
. Because of how array subscripting is defined, you can use a subscript operator on a pointer type so it looks like you're working with an array type, but you're not.In the context of a function parameter declaration,
T a[]
andT a[N]
are synonymous withT *a
, but this is only case where that is true.*char buf[] 实际上意味着 char ** 所以你是通过指针/引用传递的。
这表明 buf 在 main() 和 foo() 函数中都是一个指针。
*char buf[] actually means char ** so you are passing by pointer/reference.
That gives you that buf is a pointer, both in the main() and foo() function.
因为您正在传递一个指向
buf
的指针(按值)。所以buf
指向的内容被改变了。Because you are passing a pointer to
buf
(by value). So the content being pointed bybuf
is changed.对于指针,情况就不同了;你是按值传递的,但你传递的是指针的值,它与数组的值不同。
因此,指针的值不会改变,但您正在修改它指向的内容。
With pointers it's different; you are passing by value, but what you are passing is the value of the pointer, which is not the same as the value of the array.
So, the value of the pointer doesn't change, but you're modifying what it's pointing to.
数组和指针(几乎)是同一件事。
foo[2]
与*(foo+2*sizeof(int))
轶事相同:你写的
它也是合法的(将编译和工作相同)到写
,而且
它们实际上是相同的。它比这稍微复杂一些,因为数组知道它有多少个元素,而指针则不知道。但它们的用法是一样的。
arrays and pointers are (almost) the same thing.
foo[2]
is the same as*(foo+2*sizeof(int))
anecdote: you wrote
it is also legal (will compile and work the same) to write
and also
they are effectively the same. its slightly more complicated than that, because an array knows how many elements it has, and a pointer doesn't. but they are used the same.
为了按值传递,函数需要知道参数的大小。在这种情况下,您只是传递一个指针。
in order to pass that by value, the function would need to know the size of the argument. In this case you are just passing a pointer.
您在这里通过引用传递。在此示例中,您可以通过在所需数组的索引处传递单个字符来解决该问题。
如果要保留原始数组的内容,可以将字符串复制到函数中的临时存储中。
编辑:如果将 char 数组包装在结构中并传递该结构,会发生什么?我相信这也可能有效,尽管我不知道可能会在编译器级别产生什么样的开销。
You are passing by reference here. In this example, you can solve the problem by passing a single char at the index of the array desired.
If you want to preserve the contents of the original array, you could copy the string to temporary storage in the function.
edit: What would happen if you wrapped your char array in a structure and passed the struct? I believe that might work too, although I don't know what kind of overhead that might create at the compiler level.
请注意一件事,
声明
说,这将使用 [ ] 符号。不是您将使用数组的哪个元素。
如果你想指出这一点,你想获得一些特定的值,那么你应该声明这个函数为
当然这是不可能的,因为它是无用的(用于在数组的第n个元素进行操作的函数?)。您不必写下您想要获取数组的哪个元素的信息。您需要的一切都是简单的声明:
so...
是一个声明,说明您要使用哪种表示法( [ ] - part ),并且它还包含指向某些数据的指针。
的数组名称
此外...您会期望什么...您向函数 foo 发送了一个相当于 &buf[0] 。所以...这是一个指针。
please note one thing,
declaration
says, that will be using [ ] notation. Not which element of array you will use.
if you would like to point that, you want to get some specific value, then you should declare this function as
Of course it is not possible, because it would be useless (function for operating at n-th element of array?). You don't have to write down information which element of array you want to get. Everything what you need is simple declaration:
so...
is a declaration which says which notation you want to use ( [ ] - part ), and it also contains pointer to some data.
Moreover... what would you expect... you sent to function foo a name of array
which is equivalent to &buf[0]. So... this is a pointer.
C 中的数组不是按值传递的。它们甚至不是合法的函数参数。相反,编译器会发现您正在尝试传递数组并将其降级为指针。它默默地这样做,因为它是邪恶的。它还喜欢踢小狗。
在函数参数中使用数组是一种很好的方式,可以向 API 用户发出信号,表明该内容应该是分割成 n 字节大小的块的内存块,但不要指望编译器会关心您是否拼写
char *foo< /code> 函数参数中的
char foo[]
或char foo[12]
。他们不会。Arrays in C are not passed by value. They are not even legitimate function parameters. Instead, the compiler sees that you're trying to pass an array and demotes it to pointer. It does this silently because it's evil. It also likes to kick puppies.
Using arrays in function parameters is a nice way to signal to your API users that this thing should be a block of memory segmented into n-byte sized chunks, but don't expect compilers to care if you spell
char *foo
char foo[]
orchar foo[12]
in function parameters. They won't.