理解指针和内存地址
Understanding pointers & memory address
#include<stdio.h>
int g(int *a, int *b);
int main()
{
int a = 2;
int b = 7;
b = g(&b , &a);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
int g(int *a, int *b)
{
(*a) = (*a) + 3;
(*b) = 2*(*a) - (*b)+5;
printf("a = %d, b = %d\n", *a, *b);
return (*a)+(*b);
}
输出为:
a = 10, b = 23
a = 23
b = 33
我正在学习 C 编程入门 class 并且无法理解其工作原理。
感谢您的帮助!
通过使用 *
您可以访问指针引用的对象。由于指针引用 int
变量 a 和 b,您可以对这些变量进行操作。我认为相同的变量名称让您感到困惑
int g(int *p1, int *p2)
{
(*p1) = (*p1) + 3;
(*p2) = 2*(*p1) - (*p2)+5;
printf("*p1 = %d, *p2 = %d\n", *p1, *p2);
return (*p1)+(*p2);
}
使用&
,您将变量的地址而不是值提供给函数。
使用 *
您可以访问地址的值。
使用b = g(&b , &a);
,您将变量b
和a
的地址提供给函数。
但是您可以使用 * a
访问 b
的地址,因为您是这样声明函数的:int g (int * a, int * b)
:
*a
指向您的 b
变量的地址。
*b
指向您的 a
变量的地址。
我认为不同的变量名称让您感到困惑。
为了方便您自己,您可以将声明更改为 int g (int * b, int * a)
如果您想更改它:
*b
将指向您的 b
变量和 的地址
*a
将指向您的 a
变量的地址。
请记住,C 通过值传递所有函数参数 - 这意味着函数体中的形式参数是内存中与函数调用中的实际参数不同的对象,并将实参的值复制到形参中。
对于任何修改参数值的函数,您必须将指针传递给该参数:
void foo( T *ptr ) // for any type T
{
*ptr = new_T_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
在上面的代码中,以下所有内容都为真:
ptr == &var
*ptr == var
因此,当您向 表达式 *ptr
写入一个新值时,它与向 var
写入一个新值是一样的。
我认为让你感到困惑的部分原因是你的形式参数的名称(a
和 b
)和你的指针(a
和 b
) 被翻转 - g:a
指向 main:b
,反之亦然。
g:a == &main:b // I'm using g: and main: here strictly to disambiguate
*g:a == main:b // which a and b I'm talking about - this is not based on
// any real C syntax.
g:b == &main:a
*g:b == main:a
按问题对事件进行排序:
int main()
{
Declaration of a
and b
and value assignment:
int a = 2;
int b = 7;
Here is a trick, the address passed to the parameter int* a
is actually of b
, and vice-versa on the second parameter:
b = g(&b , &a);
Here just printing values of a
and b
:
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
Since the parameters are pointers, the changes made, in the scope of this function, to the variable addresses pointed by them are permanent:
int g(int *a, int *b) {
Here, dereferencing the pointer (*a
, the parentheses are not needed in these cases), means you are now working with the value stored in the address pointed by a
, so 7 + 3 = 10
, now the value stored in the address pointed by a
is = 10
:
(*a) = (*a) + 3;
Here, the same thing, dereferencing pointers, so 2 * 10 - 2 + 5 = 23
, the value stored in the address pointed by b
will be 23
:
(*b) = 2*(*a) - (*b)+5;
Here printing a = 10
and b = 23
, again, dereferencing pointers means you are working with the values stored in the addresses pointed by them:
printf("a = %d, b = %d\n", *a, *b);
The returned value is 10 + 23 = 33
, so for b = g(&b, &a)
, b
will be assigned the value of 33
, a
is already 23
so it stays that way:
return (*a)+(*b);
}
#include<stdio.h>
int g(int *a, int *b);
int main()
{
int a = 2;
int b = 7;
b = g(&b , &a);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
int g(int *a, int *b)
{
(*a) = (*a) + 3;
(*b) = 2*(*a) - (*b)+5;
printf("a = %d, b = %d\n", *a, *b);
return (*a)+(*b);
}
输出为:
a = 10, b = 23
a = 23
b = 33
我正在学习 C 编程入门 class 并且无法理解其工作原理。
感谢您的帮助!
通过使用 *
您可以访问指针引用的对象。由于指针引用 int
变量 a 和 b,您可以对这些变量进行操作。我认为相同的变量名称让您感到困惑
int g(int *p1, int *p2)
{
(*p1) = (*p1) + 3;
(*p2) = 2*(*p1) - (*p2)+5;
printf("*p1 = %d, *p2 = %d\n", *p1, *p2);
return (*p1)+(*p2);
}
使用&
,您将变量的地址而不是值提供给函数。
使用 *
您可以访问地址的值。
使用b = g(&b , &a);
,您将变量b
和a
的地址提供给函数。
但是您可以使用 * a
访问 b
的地址,因为您是这样声明函数的:int g (int * a, int * b)
:
*a
指向您的b
变量的地址。*b
指向您的a
变量的地址。
我认为不同的变量名称让您感到困惑。
为了方便您自己,您可以将声明更改为 int g (int * b, int * a)
如果您想更改它:
*b
将指向您的b
变量和 的地址
*a
将指向您的a
变量的地址。
请记住,C 通过值传递所有函数参数 - 这意味着函数体中的形式参数是内存中与函数调用中的实际参数不同的对象,并将实参的值复制到形参中。
对于任何修改参数值的函数,您必须将指针传递给该参数:
void foo( T *ptr ) // for any type T
{
*ptr = new_T_value(); // write a new value to the thing ptr points to
}
void bar( void )
{
T var;
foo( &var ); // write a new value to var
}
在上面的代码中,以下所有内容都为真:
ptr == &var
*ptr == var
因此,当您向 表达式 *ptr
写入一个新值时,它与向 var
写入一个新值是一样的。
我认为让你感到困惑的部分原因是你的形式参数的名称(a
和 b
)和你的指针(a
和 b
) 被翻转 - g:a
指向 main:b
,反之亦然。
g:a == &main:b // I'm using g: and main: here strictly to disambiguate
*g:a == main:b // which a and b I'm talking about - this is not based on
// any real C syntax.
g:b == &main:a
*g:b == main:a
按问题对事件进行排序:
int main() {
Declaration of
a
andb
and value assignment:int a = 2; int b = 7;
Here is a trick, the address passed to the parameter
int* a
is actually ofb
, and vice-versa on the second parameter:b = g(&b , &a);
Here just printing values of
a
andb
:printf("a = %d\n", a); printf("b = %d\n", b); return 0; }
Since the parameters are pointers, the changes made, in the scope of this function, to the variable addresses pointed by them are permanent:
int g(int *a, int *b) {
Here, dereferencing the pointer (
*a
, the parentheses are not needed in these cases), means you are now working with the value stored in the address pointed bya
, so7 + 3 = 10
, now the value stored in the address pointed bya
is= 10
:(*a) = (*a) + 3;
Here, the same thing, dereferencing pointers, so
2 * 10 - 2 + 5 = 23
, the value stored in the address pointed byb
will be23
:(*b) = 2*(*a) - (*b)+5;
Here printing
a = 10
andb = 23
, again, dereferencing pointers means you are working with the values stored in the addresses pointed by them:printf("a = %d, b = %d\n", *a, *b);
The returned value is
10 + 23 = 33
, so forb = g(&b, &a)
,b
will be assigned the value of33
,a
is already23
so it stays that way:return (*a)+(*b); }