为什么在C中使用指针?

时间:2015-04-02 22:48:31

标签: c pointers

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

我确信这是合乎逻辑的,但是我从来没有完全掌握这个概念,在阅读代码时看到*pointers总会把我抛弃。

4 个答案:

答案 0 :(得分:15)

  

变量本身是指向数据的指针

不,不是。变量表示对象,左值 lvalue 的概念与指针的概念根本不同。你好像在混淆两者。

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

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

答案 1 :(得分:9)

不,变量不是指向数据的指针。如果您使用int x, y;声明两个整数,则无法使xy引用相同的内容;它们是分开的。

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

如果您不允许使用指针或数组,那么您编写的每行代码都必须访问编译时已知的特定变量。你无法编写一段代码,它可以从内存中不同的地方读取和写入由调用者指定的内容。

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

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

答案 2 :(得分:8)

指针有用的一个常见位置是编写函数时。函数通过值'来获取它们的参数,这意味着它们获得传入的内容的副本,以及函数是否为其中一个不会影响调用者的参数分配新值。这意味着你不能写一个"加倍"功能如下:

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。

答案 3 :(得分:5)

另一个原因:C旨在构建操作系统和许多处理硬件的低级代码。每个硬件都通过寄存器公开其接口,并且几乎在所有体系结构中,寄存器都映射到CPU存储空间,并且它们不必始终位于同一地址(由于跳线设置,PnP,autoconfig等等)上)

因此,OS编写器在编写驱动程序时,需要一种方法来处理内存位置,只是他们不会引用RAM单元。

指针通过允许OS编写者指定他或她想要访问的内存位置来实现此目的。