对我来说,关于 C(以及作为 C 的继承者的 C++)最难理解的是指针,甚至是时间,它们仍然让我感到困惑。
有一个特性我还没有完全理解,我只是机械化了它的正确操作,就是通过引用函数来传递指针。
我知道在 C 中,使用与号(&)访问自动变量的引用会获取该变量的内存地址,而指针又是指向内存地址的变量;指针存储内存地址。
可以将两种类型的参数传递给 C 函数(不包括变量):值参数和参考参数。以下示例是通过引用传递给自动变量的参数的正确使用:
void funcion_init(int *varRef)
{
*varRef = 10;
}
int numero = 0;
funcion_init(&numero);
printf("%d", numero);
执行该示例后的变量numero
将是 10,到目前为止没有问题,但从这里开始就是问题。对上一个示例进行以下修改:
void funcion_init(int *varRef)
{
*varRef = 10;
}
int *numero = malloc(sizeof(int));
*numero = 0;
funcion_init(numero);
printf("%d", *numero);
执行这个例子,结果将是 0 而不是 10 预期的那样,这里我们必须做一些对我来说没有多大意义的事情:通过引用传递一个指针。但是指针不应该是内存地址本身吗?
void funcion_init(int **varRef)
{
**varRef = 10;
}
int *numero = malloc(sizeof(int));
*numero = 0;
funcion_init(&numero);
printf("%d", *numero);
当使用与号(&)指向存储要作为函数引用传递的内存地址的指针时,传递给函数的是什么,内存地址的内存地址?
这背后的逻辑是什么?
你有一个严重的概念混乱,我将把它大而大胆地说清楚:
在c语言中没有引用。
当你说:
你错了,你通过复制(而不是通过引用)将指针传递给函数。
当你说:
你错了,在 C 中你不能访问任何东西的引用,因为在 C 中引用不存在。
当你说:
你错了,将参数传递给 C 函数的唯一方法是通过复制。
当你说:
你错了,你在函数内部复制一个指针,它不是引用参数,因为在 C 语言中不存在引用。
要了解指针和引用之间的区别,请阅读这个讨论指针和引用之间差异的线程,该语言使用确实有引用的语言。
现在我将用 ASCII 艺术来说明你的例子中发生了什么:
第一个例子:
我们有一个整数(
numero
),函数funcion_init
接收一个指向整数的指针,调用varRef
其中的内存地址为numero
:et ( )运算符
&
获取变量的内存地址,该地址被复制到指针中,其方式与将数字复制到数值变量中的方式相同:通常,我们使用动词assign来将值复制到变量中,因此我们将值分配给
valor
yx
。第二个例子:
该函数
malloc
保留一个内存空间并返回一个指向该空间的指针,您将该指针复制到numero
然后将其复制到varRef
:它将打印
10
,因为两个指针都指向同一个内存。第三个例子:
该函数
malloc
分配一个内存空间并返回一个指向您复制到指针的空间的指针numero
,该函数funcion_init
接收一个指向整数的指针,称为整数varRef
,您复制的地址numero
是一个指针并询问它的地址给出一个指向指针的指针:为了更好地理解指针,我建议阅读这个线程。
首先你要明白,在C语言中,不存在引用传递的概念,因为不可能像C++等其他语言那样声明引用。
所以让我们记住三个概念:
通过引用传递:这意味着您将原始变量传递给引用,因此,在函数执行期间,我们将能够更改原始变量的内容。
按值传递:意味着您将原始变量的副本传递给参数。
指针传递:就是将原始变量传递给指针,因此,在函数执行过程中,我们可以改变原始变量的内容。
我想明确一点,在 C 中我们不使用按引用传递的概念,而是按指针传递的概念,它们基本上做同样的事情,但使用它的方式不同。
示例 1):
在本例中,它是通过指针传递的,这是因为变量的内存地址
numero
是由指针(即int* varRef
)接收的。因此,我们可以改变变量的内容numero
。示例(2):
屏幕上的结果是
10
and 这是因为在这个例子中,如果是按值传递,即发送的是 的内容的副本,numero
正好与 已预留的空间的内存地址一致malloc
。注意:这里我们没有传递指针,因为我们没有传递原始变量(在这种情况下是
int* numero
),因此,我们永远不能改变numero
.然后,在执行该功能的过程中,我们可以修改该空间的内容(您用 保留的那个
malloc
)。回答你的问题:
是的,指针在内部消耗一个内存空间,它们存储变量 X 的内存地址。
内存表示如下所示:
在这种表示中,地址
0x04
是指针的地址,它存储地址0x06
(存储值0
)。所以当你运行这个函数时:您实际传递的是地址
0x06
,为此,您必须首先访问指针的内容(在我们的示例中,指针由地址托管0x04
)。示例(3):
在这个例子中,我们通过指针传递,这是因为我们实际传递的是指针的内存地址(对我们来说是原始变量)
numero
。所以由于参数varRef
是一个双指针,它可以存储指针的内存地址,因此,我们可以在执行过程中改变两件事funcion_init
:指针的内容
numero
。用 .保留的内存空间的内容
malloc
。回答你的问题:
不完全是,您传递的只是一个内存地址。
我们用这个内存图检查它:
当这个函数运行时:
您传递的是指针所在的内存地址
numero
,在本例中为 address0x04
。因此,参数varRef
实际接收到的是指针的内存地址,也就是地址0x04
。常问问题:
C中的数组是通过引用传递的吗?
答:没有。因为C语言中不存在引用传递的概念。
我们可以说数组是指针传递的,因为你真正传递的是原始变量,这显然与数组的第一个元素的内存地址一致,因此我们可以修改原始数组。
结论:
不要在 C 中使用“按引用传递”这个术语,这会造成混淆。理想情况下,将其替换为术语pass by pointer。
别致@,在 3 种情况中的任何一种情况下,结果都是 10
如果您尝试从单个变量的角度来看,指向指针的指针的用处很小。一旦你去更多的维度,实用程序就会出现。
请注意此代码
当你做出安排时。您将始终使用指针。所以你可以做这样的事情:
既然您知道每当您使用数组时,您也会使用指针,因此您可以使用双指针指向一个二维数组。您会注意到所有程序都以
所以由于 argv 是一个数组,它也可以用指针来引用。所以你可以把它写成:
所以双指针可以说是一个指针数组。三重指针是指针数组的数组。
第二
由于 c 的工作方式,传递给函数的所有参数都是您传递给它的变量的副本。这就是为什么通过引用传递参数很重要的原因。当你传递一个指针时,你传递的是它存储的内存地址的副本。使用“&”或指针没有区别。
例如