我仍然想知道为什么在C中你不能简单地使用普通变量设置一些东西.变量本身是指向数据的指针,不是吗?那么为什么当你可以简单地使用原始变量时,指针指向变量中的数据呢?它是否可以访问所述变量中的特定位(或字节,我猜)?
我确信这是合乎逻辑的,但是我从来没有完全掌握这个概念,当阅读代码时*pointers总是把我抛弃.
AnT*_*AnT 15
变量本身是指向数据的指针
不它不是.变量表示一个对象,一个左值.的概念左值是从概念根本不同的指针.你好像在混淆两者.
在C中,不可能"重新绑定"左值以使其"指向"内存中的不同位置.在编译时确定并固定左值与其存储位置之间的绑定.它并不总是100%特定的(例如,在编译时不知道局部变量的绝对位置),但它足够具体,使其在运行时非用户可调.
指针的整个概念是它的值通常在运行时确定,并且可以在运行时指向不同的存储器位置.
tuc*_*rmi 10
指针有用的一个常见位置是编写函数时.函数通过'value'来获取它们的参数,这意味着它们获得了传入内容的副本,以及函数是否为其中一个不会影响调用者的参数赋值.这意味着你不能写这样的"加倍"函数:
void doubling(int x)
{
x = x * 2;
}
Run Code Online (Sandbox Code Playgroud)
这是有道理的,否则如果你打电话给这样的加倍,程序会做什么:
doubling(5);
Run Code Online (Sandbox Code Playgroud)
指针提供了解决此问题的工具,因为它们允许您编写带有变量地址的函数,例如:
void doubling2(int *x)
{
(*x) = (*x) * 2;
}
Run Code Online (Sandbox Code Playgroud)
上面的函数将整数的地址作为参数.函数体中的一行取消引用该地址两次:在等号的左侧,我们存储到该地址,在右侧,我们从该地址获取整数值,然后将其乘以2最终结果是在该地址找到的值现在加倍.
顺便说一句,当我们想要调用这个新函数时,我们不能传入一个文字值(例如doubling2(5)),因为它不会编译,因为我们没有正确地给函数一个地址.给它一个地址的一种方法是这样的:
int a = 5;
doubling2(&a);
Run Code Online (Sandbox Code Playgroud)
最终结果是我们的变量a将包含10.
不,变量不是指向数据的指针.如果你用两个整数声明int x, y;,那么就没有办法制作x和y引用同一个东西; 他们是分开的.
无论何时从变量读取或写入,您的计算机都必须以某种方式确定该变量在计算机内存中的确切位置.您的计算机将查看您编写的代码并使用它来确定变量的位置. 指针可以表示编译代码时未知位置的情况; 确切地址仅在您实际运行代码时才计算.
如果不允许使用指针或数组,那么您编写的每行代码都必须访问编译时已知的特定变量.您无法编写从调用程序指定的内存中不同位置读取和写入的一般代码.
注意:您还可以使用带有变量索引的数组来访问在编译时位置未知的变量,但是数组通常只是指针的语法糖.您可以考虑使用指针操作来考虑所有数组操作.数组不如指针灵活.
另一个警告:正如AnT指出的那样,局部变量的位置通常在堆栈上,因此它们是一种变量,其中位置在编译时是未知的.但是堆栈用于在可重入函数中存储局部变量的唯一原因是你的编译器实现了被称为堆栈指针和/或帧指针的隐藏指针,函数使用这些指针来找出哪个部分的内存保存了它们的参数和本地变量. 指针是非常有用的,编译器实际上在你的背后使用它们而不告诉你.
另一个原因:C被设计为构建操作系统和许多处理硬件的低级代码。每个硬件都通过寄存器公开其接口,并且在几乎所有体系结构上,寄存器都映射到CPU内存空间中,并且它们不必始终位于同一地址中(这要归功于跳线设置,PnP,自动配置等)。上)
因此,OS编写器在编写驱动程序时,需要一种方法来处理似乎是内存的位置,只是要确保它们不引用RAM单元。
指针通过允许OS编写器指定他或她想要访问的存储位置来达到此目的。