这个简单程序中的指针使用有什么问题?

时间:2014-09-05 04:50:50

标签: c

我正在使用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只是为了在一个更大的程序中创建一个类似的问题,但是我不认为人们想要筛选所有代码只是为了解决这个问题。 ,显示在这里。

3 个答案:

答案 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,声明模仿使用规则意味着ppcchar **ppc;类型的值。因此,这意味着**ppcchar类型的值。这意味着当您写入*ppc时,您正在修改char *指向的空间,并指向示例代码中*ppcppc的地址。

答案 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

现在pptrint**)可以修改ptrint*)所指向的位置。如果您要修改pptr,那么您需要更高级别ppptrint***),依此类推。