【问题标题】:Pointers, references, C指针、引用、C
【发布时间】:2011-12-15 07:47:36
【问题描述】:

我学习的第一门编程语言是 Actionscript,我很难理解指针和引用。

当我只能使用引用时,指针的目的是什么?我读过一个指针的用例是将一个大变量提供给另一个函数而不是复制它,但我不能只在前面添加一个 & 使其像指针一样起作用吗?

(我知道知道/传递某物的内存地址有多大帮助,但我不明白为什么有 &)

编辑:我的意思是使用 & 的引用

【问题讨论】:

标签: c


【解决方案1】:

指针和&-构造没有区别。指针是一个存储 &... 值的变量。

int a;
int *b = &a;

【讨论】:

    【解决方案2】:

    C 中的引用是一个指针,因此当您通过引用传递时,您将参数的地址提供给函数。

    void foo(mybigStruct *p);
    
    mybigstruct S;
    
    foo( &S ); // passing S by reference which is the same as
    
    mybigstruct *p = &S;
    
    foo( p ); // p points to address of S
    

    与仅将参数复制到函数的值传递相反,通过引用(ptr)传递允许函数修改其参数,因为函数可以直接访问传递数据所在的特定内存地址的原始位置即上例中S可以被foo修改。

    【讨论】:

      【解决方案3】:

      如果您还没有,我建议您观看Binking Pointer Fun 视频。它们以温和的方式提供丰富的信息......而且非常有趣。


      C 没有引用。 Java 和 ActionScript 之类的语言——尽管作为 AS 的基础的 ECMAScript,在规范中没有提及引用——使用术语“引用”本质上是指“总是引用的指针 [值]到一个有效的对象”。

      C 没有引用。它有指针。指针更加基本和原始,并且不能保证它们指向一个有效的对象。

      还要注意,Java 和 ActionScript(和 C)都是 call-by-value(尽管在 Java 中“传递对象”或在 C 中“传递指针”时,请参阅 call-by-object-sharing 以获得更好的高级术语)。在 Java 中,当您将对象传递给方法时,底层实现会传递表示该对象的 reference 值:in 非常类似于将 pointer 值传递给 C 中的函数。

      编码愉快。

      【讨论】:

      • @gladoscc 也许您可以发布一些代码(编辑主要问题)?我相信您的意思是 & 表示“地址”运算符,但一个真实的例子会更清楚地说明您的问题。
      【解决方案4】:

      C 没有引用,它们是 C++ 特性。 C 具有指针,这些指针本质上是保存内存地址的特殊变量。当您使用 * 运算符取消引用指针时,您是在告诉编译器您想要存储在指针中的地址处的值。 & 运算符表示“地址”,因此&i 表示变量 i 的地址。

      // create an integer variable holding the value 1
      int i = 1;
      
      // create a pointer to an integer and set the value of the pointer to the address of i
      int * ptr = &i
      
      // print the value at the address pointed to by ptr by dereferencing the pointer
      printf("%i\n", *ptr); // prints 1
      

      您可以将指针视为一个引用,因为它指向一个值的实例(在大多数用例中)。当然,指针可以指向与指针所包含的位数相符的任何内存地址,这就是 C 语言如此容易自取其辱的原因。

      【讨论】:

      • “它指向一个值的实例(理论上)”——在 C 中,指针不需要指向一个值的实例......它可以合法地指向一个值内部,甚至是刚刚超过一个值的地址。
      • 因此是“(理论上)” - 但也许这不是最好的词。通常大多数开发人员(包括那些需要询问 & 运算符的开发人员)都希望他们的指针指向结构或其他变量的实例。
      • 确实这是一个错误的词,因为 C 的唯一“理论”是由标准定义的。你说的是实践,不是理论。
      【解决方案5】:

      从技术上讲,指针和引用在 C++ 中是相同的(C 只有指针)。概念上的区别是引用保证表示有效对象,而指针可以表示无效对象(空指针)。使用指针还是引用是非常有情境的,也是个人喜好的问题。

      【讨论】:

      • 首先,这不是一个 C++ 问题,所以用 C++ 回答是不恰当的。其次,指针和引用在 C++ 中是不一样的,无论是技术上还是其他方面。我建议你阅读en.wikipedia.org/wiki/Reference_%28C%2B%2B%29
      【解决方案6】:

      指针和引用之间的一个很大区别是指针可以为空。这可用于附加信息,例如在函数调用中。引用总是需要它“引用”的“备份”。因此,如果函数的参数可以为空,则将使用指针,否则引用将更适合。

      另一件事是函数的返回值。从理论上讲,您可以返回对函数局部变量的引用,但您的程序很可能会崩溃,因为该函数已从堆栈中删除,并且该引用将不再有可用的“备份”。在这种情况下,必须使用指向新分配内存的指针。

      另一个用例是指向指针的指针,例如作为函数的参数。然后该函数可以在原始指针处分配数据。

      事实上,c 中的指针是一个巨大的话题,其中的陷阱和最佳用法最好通过实践来学习和理解。

      【讨论】:

      • "因此,如果函数的参数可以为空,则使用指针,否则引用会更合适。" -- 这是一个 C 问题,而不是 C++。 C 没有引用。
      【解决方案7】:

      当我只能使用引用时,指针的目的是什么?我读 指针的一个用例是将一个大变量提供给另一个 函数而不是复制它,但我不能只在前面添加一个 & 它就像一个指针?

      好的,这是一个“大变量”:

      struct foo {
         int a[10000];
      } biggie;
      

      这里我们通过在它前面添加& 将它传递给一个函数:

      some_function(&biggie);
      

      但是这个函数是什么样子的呢?

      void some_function(struct foo* ptr)
      {
          ...
      }
      

      看,&biggie 是一个字面量指针,是 biggie 的地址,ptr 是一个变量指针,可以指向任何 struct foo

      【讨论】:

        【解决方案8】:

        在函数中,您可以递增/递减指针参数;您不能更改参考参数。后者可以防止你在脚下射击自己。我怀疑引用(以及 Java 和 C#)是在管理层意识到他们的大量程序员永远不会正确获取指针并且注定要在他们的应用程序。

        引用也更容易阅读('ref.field' 而不是 'ptr->field')。出于这个原因,我尽可能使用引用而不是指针。

        如果一个函数正在分配内存,双指针似乎更自然:

        void foo(char **ptr)
        {   *ptr = (char *)malloc(1000);
        }
        

        引用声明似乎倒退了:

        void bar(char * &ptr)    // I would have expected char &*ptr ?
        {    ptr = (char *)malloc(1000);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-19
          • 2019-05-20
          相关资源
          最近更新 更多