我在这里有点困惑。这是一本很棒的C书,也许我对它的质疑太多了,但不知何故它没有意义。我希望我能说出我的困惑。
让我们说下面&a
指向内存地址87,&b
指向内存地址120;
int a = 3;
int b = 4;
swap(&a, &b);
void swap(int *px, int *py) {
int temp;
temp = *px;
*px = *py;
*py = temp;
}
好的,这是一个问题:当我们调用函数交换并将参数传递给函数时,我们实际上是将“px”设置为87还是将“* px”设置为87? < / p>
因为如果我们将* px设置为87然后根据*
符号的定义,我们设置指针引用的值,而不是内存地址p,这在本例中是错误的。另一方面,如果我们实际上将“p”设置为87,那么swap中的代码是有意义的,因为当我们在函数中使用*符号时,我们将引用该地址中的值“3”这里。但那么为什么语法会让人感到困惑,看起来好像我们正在设置
*px = 87
答案 0 :(得分:4)
如果a
位于地址88(需要正确对齐)且b
位于地址120,则:
// a | b | px | py | temp
int a=3; // 3 -- -- -- --
int b=4; // 3 4 -- -- --
swap(&a, &b); // 4 3 -- -- --
void swap(int *px, int *py)
{ // 3 4 88 120 --
int temp;
temp = *px; // 3 4 88 120 3
*px = *py; // 4 4 88 120 3
*py = temp; // 4 3 88 120 3
}
px
&a
为88
,永不改变。
*px
指(别名)a
。它可以反弹为别名变量,但是这段代码不会这样做。
参数为px
,类型为int*
。参数不是*px
。出于这个原因,许多程序员将其写为int* px
而不是int *px
。调用swap(&a, &b)
的效果是px = &a
而非*px = &a
。
但请注意,C没有“方法”,只有“功能”。
答案 1 :(得分:2)
考虑您swap
的签名:
void swap(int *px, int *py);
这意味着swap需要两个指向int
的指针。另一种说法:在内存中需要两个int
值的地址。
现在,在调用您的swap
函数时
swap(&a, &b);
第一个参数将是a
的地址(int
),第二个参数将是b
的地址(int
同样)。
在swap
内,px
将是a
的地址,py
将是b
的地址。因此,解除引用 px
和py
将生成a
和b
地址的值 - 这将是3和4。
答案 2 :(得分:2)
*
可能意味着三个不同的东西,具体取决于具体情况:
a * b
中,它意味着乘法。int *a
中,它表示“我们现在声明变量或参数a
,其类型为int *
(指向int
的指针)。*a
中(假设*
左侧没有数据类型,因此这是表达式而不是声明),这意味着“a
是一个指针,我们希望查看它指向的值(也称为解除引用指针”。因此,您方法的参数为a
,而不是*a
;星号是参数类型的一部分,而a
是你设置为87.将指针声明写为int * a
或int* a
而不是int *a
可能有助于区分宣言和解除引用之间更清楚。
答案 3 :(得分:1)
void swap(int *px, int *py)
您认为px
和py
指向int
。 C中的参数按值传递。因此,当您将两个内存地址(即指针)传递给swap
时,您将这些地址分配给px
和py
。
也许混淆是由于C中*
的重载过多。在参数列表中*
表示该参数是指向左侧类型的指针。在函数的实现中,*
用于取消引用指针。
答案 4 :(得分:1)
您没有设置任何指针,您始终只设置指针的值。 *px = *py
会将a
设置为b
的值。
答案 5 :(得分:1)
变量a
指向内存地址87. &a
是 87.然后我们将px
设置为87.当然,这些是地址和不是整数,但这与CPU上发生的事情非常接近(当然在CPU上没有a
,&a
或px
。
答案 6 :(得分:0)
我们实际上是将“px”设置为87还是将“* px”设置为87?
是的,您将 px 设置为87.您正在更改指向的值时指针指向同一位置。
“因为如果我们将* px设置为87”......
不,你的假设是错误的。