好了,既然你已经完全理解&
和*
操作了,剩下的就很简单了。
假设您有:
int q;
int *m;
m = &q;
那么如果你说:
int *m2;
m2 = m;
m2
将包含与 相同的值m
,也就是说,它将具有 的地址q
。因此,*m
and*m2
会给你相同的值(也就是 的值q
)(你明白那*
是对的逆运算符&
吗?所以*(&q) = q
and &(*m) = m
(在后面的情况下,m
需要是一个指针*
才能适用。))
那么,这如何与函数一起使用?简单的!当您将参数传递给函数时,您按值传递它们。当你通过指针传递时,你实际上是通过值传递,即变量的指针。
因此,让我们详细检查您的函数调用:
reverse_number(in_orig, &out_orig);
我将您的in_val
and重命名out_val
为in_orig
,out_orig
因此它不会与reverse_number
.
现在,&out_orig
是 的地址out_orig
。当作为参数传递时,它被复制out_val
到reverse_number
. 这和写作完全一样:
int *out_val = &out_orig;
现在,如果您的 中包含上述行main
,您可以编写*out_val = something;
它并且它会改变out_orig
,对吗?好吧,既然你有out_orig
in的地址out_val
,那么谁在乎是否*out_val
设置在main
or reverse_number
?
所以你看?当你有一个指针时,你可以复制它,无论是将它复制到另一个变量还是将它作为函数的参数传递(这基本上是同一件事),你仍然可以访问它指向的同一个变量。毕竟,所有副本都具有相同的值:地址out_orig
。现在,如果您想在 function 或 in 中访问它main
,这并不重要。
编辑:*
在指针定义中
*
*
也可以用于定义指针,这与之前用作获取地址值的运算符无关。
这只是定义,所以你必须学习它:
如果您有一个类型的值type
(例如int
),那么该变量的地址(使用operator &
)具有类型type *
(在本例中int *
)。由于指针采用该地址,因此指针的类型为type *
。
相反,如果指针具有类型type *
(例如int *
),则获取指针指向的值(使用operator *
)具有类型type
(在本例中int
)。
总之,你可以这样说:
operator &, adds one * to the type of the variable
operator *, removes one * from the type of the expression
所以让我们看一些例子:
int x;
x has type int
&x has type int *
float *y;
y has type float *
&y has type float **
*y has type float
struct Data ***d;
d has type struct Data ***
&d has type struct Data ****
*d has type struct Data **
*(*d) has type struct Data *
*(*(*d)) has type struct Data
如果你注意到了,我说过&
给*
variable 的类型加一个,但从expression的类型中*
删除一个。这是为什么?因为给出了变量的地址。当然,因为没有其他东西有地址。例如(可能)在内存中没有任何地址,如果有,它只是暂时的和无用的。*
&
a+b
operator *
但是,适用于地址。无论您如何计算地址,都operator *
可以使用它。例子:
*(0x12345678) -> Note that even if the compiler let's you do this,
your program will most likely crash
*d -> like we saw before
*(d+4) -> This is the same as writing d[4]
And now you know why arrays and pointers are treated as one
如果是动态二维数组:
*(*(d+4)+6) -> This is the same as writing d[4][6]