Ins*_*ane 65 c pointers pass-by-reference
在我大学的C编程课程中,教授及其后来的书在引用C中的指针时使用了术语调用或通过引用传递.
我的教授称之为"参考函数调用"的一个例子:
int sum(int *a, int *b);
Run Code Online (Sandbox Code Playgroud)
我的教授称之为"价值函数呼叫"的一个例子:
int sum(int a, int b);
Run Code Online (Sandbox Code Playgroud)
我读过 C不支持通过引用调用.根据我的理解,指针通过值传递.
基本上,说指针是C通过引用传递的方式是不正确的吗?说你不能通过C中的引用传递但是可以使用指针替代它会更正确吗?
2015年11月11日更新
从我的问题起源的方式来看,我认为术语的争论已经产生,实际上我看到了两个具体的区别.
在阅读了@Haris的更新答案之后,为什么这不是那么黑白,这是有道理的.
Har*_*ris 56
你不能通过C中的引用传递,但可以使用指针作为替代
是的,那是正确的.
详细说明一点.无论你作为c函数的参数传递什么,它都只通过值传递.无论是变量值还是变量地址.
是什么让你与众不同.
当我们传递值时,我们将变量的值传递给函数.当我们传递引用时,我们将变量的别名传递给函数.C可以将指针传递给函数,但仍然是按值传递.它将指针的值(地址)复制到函数中.
如果要发送变量的值,则该函数仅接收该值,并且更改该值不会影响原始值.
如果要发送变量的地址,那么也只发送值(本例中的地址),但由于您具有变量的地址,因此可以使用它来更改原始值.
作为一个例子,我们可以看到一些C++代码来理解call-by-value和call-by-reference之间的真正区别.取自本网站.
// Program to sort two numbers using call by reference.
// Smallest number is output first.
#include <iostream>
using namespace std;
// Function prototype for call by reference
void swap(float &x, float &y);
int main()
{
float a, b;
cout << "Enter 2 numbers: " << endl;
cin >> a >> b;
if(a>b)
swap(a,b); // This looks just like a call-by-value, but in fact
// it's a call by reference (because of the "&" in the
// function prototype
// Variable a contains value of smallest number
cout << "Sorted numbers: ";
cout << a << " " << b << endl;
return 0;
}
// A function definition for call by reference
// The variables x and y will have their values changed.
void swap(float &x, float &y)
// Swaps x and y data of calling function
{
float temp;
temp = x;
x = y;
y = temp;
}
Run Code Online (Sandbox Code Playgroud)
在这个C++示例中,正在使用引用变量(在C中不存在).引用这个网站,
"引用是别名,或现有变量的替代名称......",
和
"引用的主要用途是作为函数形式参数来支持传递引用......"
这与使用指针作为函数参数不同,因为,
"指针变量(或简称指针)基本上与其他变量相同,后者可以存储一段数据.与存储值的常规变量(如int,double,char)不同,指针存储一个记忆地址."
因此,基本上当一个人发送地址并通过指针接收时,一个人只发送值,但是当一个人发送/接收一个参考变量时,一个人正在发送一个别名或一个引用.
在C聊天室进行了长时间的辩论,在阅读了这个问题的评论和答案之后,我意识到可以有另一种方式来看待这个问题,另一种观点是.
让我们看一些简单的C代码
int i;
int *p = &i;
*p = 123;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可以使用术语,p的值是对i的引用.因此,如果是这种情况,那么如果我们向int* p函数发送相同的指针(),可以认为,因为i引用被发送到函数,因此这可以被称为pass-by-reference.
所以,这是一个术语问题和观察场景的方式.
我不会完全不同意这一论点.但对于一个完全遵循这本书和规则的人来说,这是错误的.
注意:更新的灵感来自于这个聊天.
小智 32
参考是一个重载的术语; 一般来说,引用只是一种引用某种东西的方式.指针指向指向的对象,并且通过(通过值)传递指向对象的指针是在C中通过引用传递的标准方式.
C++引入了引用类型作为表达引用的更好方式,并引入了技术英语的歧义,因为我们现在可以使用术语"通过引用传递"来引用使用引用类型来通过引用传递对象.
在C++上下文中,前者的使用是IMO,不推荐使用.但是,我认为前一种用法在其他情况下很常见(例如纯C),其中没有歧义.
hac*_*cks 17
并不是的.
严格来说,C总是使用pass by value.您可以自己模拟通过引用传递,通过定义接受指针的函数然后
&在调用时使用运算符,并且当您将数组传递给函数时,编译器将基本上为您模拟它(通过传递指针,请参阅问题6.4 et人).查看它的另一种方法是,如果参数具有类型,比如说,
int *则通过引用传递整数,并且通过值传递指向整数的指针.从根本上说,C没有任何真正等同于通过引用或c ++引用参数的正式传递.
为了演示指针是按值传递的,让我们考虑使用指针进行数字交换的示例.
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
int ptemp;
printf("Before swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
temp = pnum1;
pnum1 = pnum2;
pnum2 = ptemp;
printf("After swap, *Pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Run Code Online (Sandbox Code Playgroud)
而不是交换数字指针被交换.现在为此做一个功能
void swap(int *pnum1, int *pnum2)
{
int *ptemp = pnum1;
pnum1 = pnum2;
pnum2 = temp;
}
int main(void)
{
int num1 = 5;
int num2 = 10;
int *pnum1 = &num1;
int *pnum2 = &num2;
printf("Before swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
swap(pnum1, pnum2);
printf("After swap, *pnum1 = %d and *pnum2 = %d\n", *pnum1, *pnum2);
}
Run Code Online (Sandbox Code Playgroud)
繁荣!没有交换!
一些教程提到指针引用为引用调用,这是误导性的.请参阅此答案,了解通过引用传递和传递值之间的区别.
R S*_*ahu 16
从C99标准(强调我的):
6.2.5类型
20可以从对象和函数类型构造任意数量的派生类型,如下所示:
...
- 指针典型可以从函数类型或对象类型派生,称为引用类型.指针类型描述一个对象,其值提供对引用类型的实体的引用.从引用类型T派生的指针类型有时被称为"指向T "的指针.从引用类型构造指针类型称为"指针类型派生".指针类型是完整的对象类型.
基于以上所述,你的教授所说的是有道理的,也是正确的.指针通过值传递给函数.如果指针指向有效实体,则其值提供对实体的引用.
小智 10
"通过引用传递"是一个概念.是的,您正在传递指向函数的指针的值,但在该实例中,该指针的值用于引用该变量.
其他人使用螺丝刀类比来解释说通过引用传递指针是错误的,说你可以用硬币拧螺丝,但这并不意味着你会把硬币称为螺丝刀.我会说这是一个很好的类比,但他们得出了错误的结论.事实上,虽然你不会要求硬币是一把螺丝刀,你仍然会说你用螺丝拧紧螺丝.即使指针与c ++引用不同,你使用它们做的是通过引用传递的.
小智 6
C按值,句点传递参数.但是,指针是一种可用于通过引用有效传递参数的机制.就像硬币可以有效地用作螺丝刀一样,如果你有合适的螺丝钉:甚至可以选择一些螺丝切割以便与硬币一起使用.他们仍然不会将硬币变成实际的螺丝刀.
C++仍然按值传递参数.C++引用比指针更有限(虽然有更多的隐式转换)并且不能成为数据结构的一部分,并且它们的使用看起来更像通常的引用调用代码看起来,但是它们的语义,同时非常适合为了满足call-by-reference参数的需要,它们比纯var函数调用实现(如Fortran参数或Pascal 参数)更有形,你可以在函数调用上下文之外完美地使用引用.
你的教授是对的.按值,它被复制.通过引用,它不会被复制,引用说明它在哪里.
通过值,您将一个int传递给一个函数,它被复制,对副本的更改不会影响原始函数.
通过引用,传递相同的int作为指针,它不被复制,您正在修改原始.
通过引用,一个数组总是通过引用,你的数组中可能有十亿个项目,只是说它在哪里,你正在修改原始数据更快.