【问题标题】:Why Use Pointers in C?为什么在 C 中使用指针?
【发布时间】:2015-06-08 01:06:09
【问题描述】:

我仍然想知道为什么在 C 中你不能简单地使用普通变量将某物设置为另一物。变量本身就是指向数据的指针,不是吗?那么,当您可以简单地使用原始变量时,为什么要让指针指向变量中的数据呢?是访问所述变量中数据的特定位(或字节,我猜)吗?

我确信这是合乎逻辑的,但是我从未完全掌握这个概念,并且在阅读代码时看到 *pointers 总是让我感到厌烦。

【问题讨论】:

  • 在学习的过程中,我发现无论看起来多么复杂,指针都是保存内存地址的变量更容易记住。所以char ***p 很可怕,但它最终只拥有一个内存地址。
  • 如果“原始变量”是一个 10MB 的网络缓冲区怎么办?你将如何将它传递给一个函数,复制它?你如何将它排入另一个线程,复制两次?
  • @MartinJames 很好的提示。

标签: c pointers


【解决方案1】:

指针有用的一个常见地方是编写函数时。函数“按值”获取参数,这意味着它们会获取传入内容的副本,并且如果函数为其参数之一分配新值,则不会影响调用者。这意味着您不能编写这样的“加倍”函数:

void doubling(int x)
{
    x = x * 2;
}

这是有道理的,否则如果你像这样调用加倍,程序会做什么:

doubling(5);

指针提供了解决此问题的工具,因为它们让您可以编写获取变量地址的函数,例如:

void doubling2(int *x)
{
    (*x) = (*x) * 2; 
}

上面的函数接受一个整数的地址作为它的参数。函数体中的一行取消引用了两次地址:在等号的左侧,我们存储到该地址中,在右侧,我们从该地址获取整数值,然后将其乘以 2 . 最终结果是在该地址找到的值现在翻了一番。

顺便说一句,当我们想要调用这个新函数时,我们不能传入一个文字值(例如doubling2(5)),因为我们没有正确给出函数一个地址。给它一个地址的一种方法如下所示:

int a = 5;
doubling2(&a);

这样做的最终结果是我们的变量a 将包含 10。

【讨论】:

  • 我最喜欢这个答案。它直截了当,示例简约但非常好。
  • 与往常一样,做事最好的方式就是自己动手。我测试了这个脚本并且很好理解
【解决方案2】:

变量本身就是一个指向数据的指针

不,不是。一个变量代表一个对象,一个左值lvalue 的概念与 pointer 的概念根本不同。你好像把两者混在一起了。

在 C 中,不可能“重新绑定”左值以使其“指向”内存中的不同位置。左值和它们的内存位置之间的绑定是在编译时确定和固定的。它并不总是 100% 特定的(例如,局部变量的绝对位置在编译时是未知的),但它足够特定以使其在运行时无法由用户调整。

指针的整体思想是它的值通常在运行时确定,并且可以在运行时指向不同的内存位置。

【讨论】:

  • 一个左值可以被反弹,例如如果p 是一个指针,*p 是一个左值,可以通过改变p 的值来引用不同的对象。你的意思是命名对象你说“左值”
【解决方案3】:

不,变量不是指向数据的指针。如果你用int x, y;声明两个整数,那么就没有办法让xy指向同一个东西;它们是分开的。

每当您从变量读取或写入时,您的计算机必须以某种方式确定该变量在计算机内存中的确切位置。您的计算机将查看您编写的代码并使用它来确定变量的位置。 指针可以表示在编译代码时位置未知的情况;只有在您实际运行代码时才会计算出确切的地址。

如果不允许您使用指针或数组,则您编写的每一行代码都必须访问编译时已知的特定变量。您无法编写从调用者指定的内存中不同位置读取和写入的通用代码。

注意:您还可以使用带有变量索引的数组来访问在编译时位置未知的变量,但数组大多只是指针的语法糖。你可以用指针操作来考虑所有数组操作。数组不如指针灵活。

另一个警告:正如 AnT 所指出的,局部变量的位置通常在堆栈上,因此它们是一种在编译时位置未知的变量。但是堆栈用于在reentrant 函数中存储局部变量的唯一原因是您的编译器实现了称为堆栈指针和/或帧指针的隐藏指针,并且函数使用这些指针来找出内存的哪一部分保存它们的参数和局部变量。 指针非常有用,编译器实际上会在你背后使用它们而不告诉你。

【讨论】:

    【解决方案4】:

    另一个原因:C 旨在构建操作系统和大量处理硬件的低级代码。每个硬件都通过寄存器公开其接口,并且在几乎所有架构上,寄存器都映射到 CPU 内存空间,并且它们不必总是位于相同的地址(多亏了跳线设置、PnP、自动配置等)开)

    因此,例如,在编写驱动程序时,操作系统编写者需要一种方法来处理看似内存位置的内容,只是它们不引用 RAM 单元。

    指针通过允许操作系统编写者指定他或她想要访问的内存位置来达到此目的。

    【讨论】:

    • 几乎所有的架构...除了最常用的一个;)
    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多