【问题标题】:Understanding pointers & memory address理解指针和内存地址
【发布时间】:2020-07-03 06:11:03
【问题描述】:
#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 编程入门课程,但无法理解其工作原理。

感谢您的帮助!

【问题讨论】:

    标签: c pointers memory-address


    【解决方案1】:

    对有问题的事件进行排序:

    int main()
    {  
    

    ab的声明和赋值:

        int a = 2;
        int b = 7;
    

    这里有一个技巧,传递给参数int* a的地址实际上是b,反之亦然第二个参数:

        b = g(&b , &a);
    

    这里只打印ab 的值:

        printf("a = %d\n", a);
        printf("b = %d\n", b);
    
        return 0;
    }
    

    由于参数是指针,因此在此函数范围内,对它们所指向的变量地址所做的更改是永久性的:

    int g(int *a, int *b) {
    

    这里,取消引用指针(*a,在这些情况下不需要括号),意味着您现在正在使用存储在a 指向的地址中的值,所以7 + 3 = 10,现在存储的值在a指向的地址中是= 10

        (*a) = (*a) + 3;
    

    这里,同样的事情,解引用指针,所以2 * 10 - 2 + 5 = 23,存储在b指向的地址中的值将是23

        (*b) = 2*(*a) - (*b)+5;
    

    这里再次打印a = 10b = 23,取消引用指针意味着您正在处理存储在它们指向的地址中的值:

        printf("a = %d, b = %d\n", *a, *b);
    

    返回值为10 + 23 = 33,因此对于b = g(&amp;b, &amp;a)b 将被赋值为33a 已经是23,所以它保持这种状态:

        return (*a)+(*b); 
    }
    

    【讨论】:

      【解决方案2】:

      请记住,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 写入新值相同。

      我认为让您感到困惑的部分原因是您的形式参数的名称(ab)和您的指针(ab)被翻转 - 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
      

      【讨论】:

        【解决方案3】:

        使用&amp;,您将变量的地址而不是值提供给函数。 使用*,您可以访问地址的值。

        使用b = g(&amp;b , &amp;a);,您将变量ba 的地址提供给函数。 但是您可以使用* a 访问b 的地址,因为您以这种方式声明函数:int g (int * a, int * b)

        • *a 指向您的 b 变量的地址。
        • *b 指向您的 a 变量的地址。

        我认为不同的变量名会让你感到困惑。

        为了方便您自己,您可以将声明更改为 int g (int * b, int * a) 如果你想改变它:

        • *b 将指向您的 b 变量的地址,并且
        • *a 将指向您的 a 变量的地址。

        【讨论】:

          【解决方案4】:

          通过使用*,您可以访问指针所引用的对象。由于指针引用 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);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-12-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多