指针是否考虑了在C中通过引用调用的方法?

在我的大学的C语言程序devise课上,她所写的教授和随后的书在引用C中的指针时使用了call或pass by reference这个术语。

我的教授认为是“引用函数”的一个例子:

int sum(int *a, int *b); 

我的教授认为是“价值函数”的一个例子:

 int sum(int a, int b); 

我读过 C不支持通过引用调用。 就我的理解而言, 指针传递的是价值

基本上,说指针是C通过引用传递的方式是不正确的 ? 如果你不能通过C语言的引用传递,但是可以使用指针作为替代方法,会更准确吗?


更新11/11/15

从我提出的问题的方式来看,我认为有关术语的辩论已经出现,实际上我看到了两个具体的区别。

  • 传递引用(当前主要使用的术语):在C ++等语言中使用的特定术语
  • 通过引用(我的教授用作解释指针的范式的术语):在C ++之类的语言之前使用的通用术语被开发出来,因此在术语被重写之前

在阅读@Haris更新后的答案之后,为什么这不是那么黑白。

你不能在C中通过引用传递,但可以使用指针作为替代

是的,这是正确的。


再详细一点。 不pipe你作为c函数的parameter passing什么,它只是通过值传递。 无论是variables的值还是variables的地址。

造成这种差别的是你发送的内容。

当我们传值时,我们将variables的值传递给一个函数。 当我们传递参考时,我们将variables的别名传递给一个函数。 C可以将一个指针传入一个函数,但仍然是按值传递的。 它将指针的值,地址复制到函数中。


  • 如果你正在发送一个variables的值,那么只有该值将被该函数接收,并且改变它将不会影响原始值。

  • 如果你正在发送一个variables的地址,那么也只是发送这个值(这个地址),但是由于你有一个variables的地址,所以它可以用来改变原来的值。


作为一个例子,我们可以看到一些C ++代码来理解按值调用和按引用调用之间的真正区别。 采取从这个网站。

 // 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; } 

在这个C ++示例中,正在使用引用variables (不存在于C中)。 引用这个网站,

“引用是一个别名,或一个现有variables的替代名称…”

“引用的主要用途是作为函数forms参数来支持通过引用……”

这与使用指针作为函数参数是不同的,因为,

“指针variables(或简称指针)与其他variables基本相同,可以存储一个数据,与存储一个值的普通variables(如int,double,char)不同,指针存储一个内存地址“。

所以,基本上当一个人通过指针发送地址和接收时,一个人只是发送这个值,但是当一个人发送/接收一个参考variables时,一个人正在发送一个别名或一个引用。


更新:2015年11月11日

C聊天室已经有很长一段时间的争论,在阅读了这个问题的评论和回答之后,我意识到可以有另一种方式来看待这个问题,也就是说。

让我们看看一些简单的C代码

 int i; int *p = &i; *p = 123; 

在这种情况下,人们可以使用这个术语, p的值是对i的引用 。 所以,如果是这样的话,那么如果我们把相同的指针( int* p )发送给一个函数,就可以争辩说,因为i的引用被发送给函数,所以这可以被称为pass-by-参考

所以,它是一个术语和观察场景的方式。

我不会完全不同意这个说法。 但对于一个完全遵循这本书和规则的人来说,这是错误的。


注意:更新启发了这个聊天。

引用是一个超负荷的术语。 一般而言,参考仅仅是指某种方式。 指针指向指向的对象,并且传递(通过值)指向对象的指针是在C中通过引用传递的标准方式。

C ++引入了引用types作为expression引用的一种更好的方式,并且引入了对技术英语的歧义,因为我们现在可以使用术语“通过引用”来引用使用引用types来通过引用传递对象。

在C ++上下文中,以前的用法是,IMO,已弃用。 但是,我相信前者的使用在其他没有歧义的情况下是常见的(例如纯粹的C)。

从C99标准(重点矿):

6.2.5types

20可以从对象和函数types构造任意数量的派生types,如下所示:

指针types可以从函数types或对象types派生,称为引用types指针types描述了一个对象,它的值提供了引用types实体的引用 。 从引用typesT派生的指针types有时被称为“指向T的指针”。 从引用types构造指针types称为“指针types推导”。 指针types是一个完整的对象types。

基于以上所述,你的教授所说的是有道理的,是正确的。 指针被传递给函数。 如果指针指向一个有效的实体, 它的值提供了一个实体的引用

C甚至有“通过引用”?

不是真的。

严格来说,C总是使用价值传递。 你可以通过引用自己来模拟传递,通过定义接受指针的函数,然后在调用时使用&运算符 ,当你将一个数组传递给一个函数 ,编译器会为你模拟这个函数(通过传递一个指针,参见问题6.4等)。

另一种看待它的方法是, 如果一个参数具有types,比如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); } 

而不是交换数字指针交换。 现在做一个相同的function

 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); } 

繁荣! 不换!


有些教程提到指针引用是引用引用,这是误导性的。 通过引用传递和按值传递之间的区别看这个答案 。

“通过参考”是一个概念。 是的,您正在传递指向该函数的指针的值,但在该实例中,该指针的值正被用于引用该variables。

其他人用螺丝刀比喻来解释说把指针作为参照传递是错误的,说你可以用螺丝钉拧上一个硬币,但这并不意味着你会把硬币称为螺丝刀。 我可以说这是一个很好的比喻,但他们得出了错误的结论。 事实上,虽然你不会声称硬币是一把螺丝刀,但你仍然会说你把螺丝拧进去了。 即使指针和c ++的引用不一样,你用它们来做的事情通过引用传递的。

C按值,句点传递参数。 但是,指针是一种可以用来有效地通过引用传递参数的机制 。 就像一个硬币可以有效地作为一个螺丝起子使用,如果你得到正确的一种螺丝:一些螺丝狭缝,甚至select与硬币良好运作。 他们仍然不把硬币变成真正的螺丝起子。

C ++仍然按值传递参数。 C ++引用比指针有更多的限制(虽然有更多的隐式转换)并且不能成为数据结构的一部分,它们的使用看起来更像通常的引用调用代码看起来的样子,但是它们的语义非常符合以匹配引用参数参数的需求,比纯参考实现(如Fortran参数或Pascal var参数)的实现更加有形,并且您可以在函数调用上下文之外很好地使用引用。

你的教授是对的。 按价值,它被复制。 通过引用,它不被复制,引用说明它在哪里。

通过值,您将一个int传递给一个函数,它被复制,对副本的更改不会影响原始。

通过引用,传递相同的int作为指针,它不会被复制,您正在修改原始。

通过引用,一个数组总是被引用的,你可以在你的数组中有十亿个条目,只是说出它在哪里,你正在修改原始数据更快。

在支持通过引用的语言中,存在一种方法,通过该方法可以给函数一些东西,可以用来标识调用者知道的一个variables,直到被调用函数返回, 但是只能存储在赢得那之后就不存在了 。 因此,调用者可以知道,在函数返回的时候,通过传递某个函数引用该variables的任何操作都将在该函数返回时完成。

比较C和C#程序:

 // C // C# int x=0; int x=0; foo(&x); foo(ref x); x++; x++; bar(); bar(); x++; x++; boz(x); boz(x); 

C编译器无法知道“bar”是否可能改变x,因为foo()收到一个不受限制的指针。 相比之下,C#编译器知道bar()不可能改变x,因为foo()只接收到一个临时引用(在.NET术语中称为“byref”),并且没有办法拷贝byref生存超过foo()返回的点。

将指针传递给事物允许代码执行与通过引用语义相同的事情,但是通过引用语义使代码可以为不能做的事情提供更强的保证。