我正在使用VS 2010 Express,而我正在使用Win Vista。
以下是代码:
#include <stdio.h>
int somefunc(char *p);
int main()
{
char *p = 0;
int x;
x = somefunc (p);
printf("%c", *p);
getch();
return 0;
}
int somefunc(char *p)
{
char y = '4';
p = &y;
return 2;
}
在我返回main()
后,我在自动窗口中看到p:
p 0x00000000 <Bad Ptr>
任何人都知道为什么?就像指针被视为自动变量一样。
顺便说一下,x只是为了在一个更大的程序中创建一个类似的问题,但是我不认为人们想要筛选所有代码只是为了解决这个问题。 ,显示在这里。答案 0 :(得分:4)
您正在修改p
中的somefunc
,但这不会修改p
中的main
。如果要修改其值,可能需要将指针传递给p
。
答案 1 :(得分:4)
p
中的 main()
是空指针。它按值传递给somefunc()
,但这意味着函数中变量p
中的值是主程序中p
中值的副本,而不是指向p
本身。您可以更改函数中p
的副本指向的内容;幸运的是,它并没有改变主程序中的内容。
然后你尝试打印空指针指向的位置;这是未定义的行为,程序通常会崩溃。
如果您设法在主程序中更改p
,那么它将指向somefunc()
中的自动局部变量,该变量将超出范围 - 这是更多未定义的行为。
这样可行:
#include <stdio.h>
int somefunc(char **p);
int main(void)
{
char *p = 0;
int x = somefunc(&p);
printf("%c\n", *p);
return 0;
}
int somefunc(char **p)
{
static char y = '4';
*p = &y;
return 2;
}
还有许多其他的,可能更好的方法来完成这项工作。
我仍然对
*p = &y;
的含义感到困惑。如果p
中的somefunc
是指向指针p
的指针,请假设p2
是指向p1
的指针,然后指向*p2 = p1
,因此{ {1}}是*p2
,它存储p1
?这是正确的思考方式吗?
基本上,是的。首先,让我们重写代码以消除&y
:
p
变量int main(void)
{
char *p1 = 0;
int x = somefunc(&p1);
printf("%c\n", *p1);
return 0;
}
int somefunc(char **ppc)
{
static char y = '4';
*ppc = &y;
return 2;
}
是指向ppc
的指针(因此名称为char
- 不是我通常使用的名称,除了教学目的)。我还会将ppc
中的p
重命名为main()
,并在pq1
中引入char *p2;
,这是somefunc()
的指针。
根据这些变量修改您的评论:
我仍然对
char
的含义感到困惑。如果*ppc = &y;
中的ppc
是指向somefunc()
中指针p1
的指针,那么假设main()
是指向ppc
的指针,则{ {1}},p1
是*ppc = p1
,它存储*ppc
?这是正确的思考方式吗?
这强烈表明你的想法是正确的。 C类型术语的设计指南之一是,如果你写:
p1
然后&y
表示类型SomeType *stp;
的值 - 声明模仿使用。
现在,对于*stp
,声明为SomeType
,声明模仿使用规则意味着ppc
是char **ppc;
类型的值。因此,这意味着**ppc
是char
类型的值。这意味着当您写入*ppc
时,您正在修改char *
指向的空间,并指向示例代码中*ppc
中ppc
的地址。
答案 2 :(得分:2)
补充Jonathan的回答,提出你的问题
函数参数的char ** p和char p有什么区别?为什么我可以传递和修改数组而不必返回它,但我必须使用指针?它们都是地址。
在 C 中,没有通过引用传递,只有值传递,即传递给函数的任何参数都被复制到其参数中,但是可以&#39;可以参考原件。这就是使用指针实现像swap
这样的函数的原因。实施例
void swap(int *x, int *y)
{
int t = *x;
*x = *y;
*y = t;
}
int a = 0, b = 1;
swap(&a, &b);
此处&a
是一个指针,其值被复制到x
,因此它是按值传递的(有时,不正确,称为按引用传递)。所以我也应该在修改指针时也这样做,对吗?
不。由于指针已经指向某个东西,因此指向另一个东西需要另一个间接层。一个类比是:你知道某个方向标志指向你的家,通过知道它指向(家)的位置,你能改变它指向的方向吗?不,你必须知道标志去哪里并指向另一个方向。
同样地,如果一个变量生活在0级然后编辑它,我们进入一个级别,即级别1来修改它(从外部)。这个概念可以递归地应用;因此,要编辑级别1的变量,我们必须转到级别2以从外部修改它们,依此类推。图示地
type: int* int int*
variable name: ptr a pptr
-------- ------- --------
value: | 1000 | --> | 1 | <-- | 1000 |
-------- ------- --------
address: 2000 1000 2400
请注意pptr
无法更改ptr
指向的位置,因为pptr
也指向ptr
指向a
的内容。然而
int** int* int
pptr ptr a
-------- -------- -------
| 2000 | --> | 1000 | --> | 1 |
-------- -------- -------
2400 2000 1000
现在pptr
(int**
)可以修改ptr
(int*
)所指向的位置。如果您要修改pptr
,那么您需要更高级别ppptr
(int***
),依此类推。