2015-04-02 110 views
9

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

我敢肯定,这是合乎逻辑的,但是我从来没有充分把握的概念和读码看*pointers时总是会引发我。

+0

学习时,我发现更容易记住,无论指针看起来有多复杂,只是指向一个存储地址的变量。所以'char *** p'是可怕的想法,但它最终只拥有一个内存地址。 – teppic 2015-04-02 23:04:21

+4

如果“原始变量”是10MB网络缓冲区,该怎么办?你如何将它传递给函数,复制它?你会如何排队到另一个线程,复制两次? – 2015-04-02 23:23:54

+0

@MartinJames很好的提示。 – Gewure 2017-02-28 10:42:13

回答

13

变量本身是一个指向数据

不,事实并非如此。一个变量代表一个对象,一个左值左值的概念与指针的概念有根本的不同。你似乎混在一起了。

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

的指针的整个构思是,其值在运行时通常确定,并且可以制成指向在运行时不同的存储位置。

7

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

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

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

注意:您还可以使用数组与变量索引访问变量,其位置在编译时不知道,但是数组是指针大多只是语法糖。您可以考虑指针操作方面的所有数组操作。数组并不像指针那样灵活。

另一个警告:如蚂蚁指出的,局部变量的位置通常在堆栈上是,因此它们是一种可变的,其中位置并不在编译时已知的。但是栈函数存储局部变量的唯一原因是你的编译器实现了隐藏的指针叫做堆栈指针和/或帧指针,函数使用这些指针来找出哪部分内存存放它们的参数和局部变量。 指针非常有用,编译器实际上在背后使用它们而不告诉你。

5

指针是有帮助的一个常见的地方是当你正在写函数。函数的参数是“按值”,这意味着它们获得传入内容的副本,并且函数为其参数中的一个赋值,而不会影响调用方。这意味着,你不能写这样一个“倍增”的功能:

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

这是有道理的,因为否则将程序做,如果你这样调用加倍:

doubling(5); 

指针提供工具来解决这个问题,因为他们让你写一个采取变量的地址,例如功能:

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

上面的函数需要一个整数a的地址它的论点。函数体中的一行将这个地址解引用两次:在等号的左边,我们将存储到该地址中,在右边,我们从该地址获得整数值,然后乘以2最终的结果是在该地址找到的值现在翻倍了。

顺便说一句,当我们想要把这种新的功能,我们不能通在文字值(例如doubling2(5)),因为它不能编译,因为我们没有正确地给函数的地址。给它一个地址是这样一种方法:

int a = 5; 
doubling2(&a); 

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

+0

我最喜欢这个答案。它的直接和简单的例子是非常好的。 – Gewure 2017-02-28 10:53:48

3

另一个原因:C旨在建立操作系统和大量的处理硬件的低级代码。每一个硬件都通过寄存器来公开其接口,并且在几乎所有的体系结构中,寄存器都映射到CPU存储空间,并且它们始终不在同一个地址中(多亏了跳线设置,即插即用,自动配置等等)

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

通过允许OS编写者指定他或她想要访问的存储位置,指针用于此目的。

相关问题