【问题标题】:Why do we need pointer to a structure pointer to change members value?为什么我们需要指向结构指针的指针来更改成员值?
【发布时间】:2017-03-01 16:00:58
【问题描述】:

虽然对于简单类型(simple types: int, char..),我们直接使用指针(their address) 作为函数的参数以在主程序中永久更改它们的值,有人可以向我解释为什么对于结构我们需要指向Structure pointer 的指针,而不仅仅是一个指针?

struct someStruct
{
  int field1;
  int field2;
}

void initializeFields(struct someStruct** foo)
{
  //changing fields
}

//while 
void initializeFields(struct someStruct* foo) //does not work ?

【问题讨论】:

    标签: c pointers structure


    【解决方案1】:

    struct someStruct* foo 很好,你不需要struct someStruct** foo。不知道你从哪里得到这个想法,但它不正确。

    【讨论】:

      【解决方案2】:

      只更改不需要的结构成员。但是要将实际指针 更改为 结构,您需要通过使用指向结构的指针的指针来模拟 按引用传递

      例如,只更改一个成员就足够了

      void initializeFields(struct someStruct* foo)
      {
          foo->field1 = 1;
          foo->field2 = 2;
      }
      
      int main(void)
      {
          struct someStruct bar;
          initializeFields(&bar);
          printf("field1 = %d\n", bar.field1);
          printf("field2 = %d\n", bar.field2);
      
          return 0;
      }
      

      但是,例如,如果您想在函数中动态分配结构,则需要模拟按引用传递:

      void initializeFields(struct someStruct** foo)
      {
          // The difference is this assignment
          *foo = malloc(sizeof(struct someStruct));
      
          (*foo)->field1 = 1;
          (*foo)->field2 = 2;
      }
      
      int main(void)
      {
          struct someStruct* bar;
          initializeFields(&bar);
          printf("field1 = %d\n", bar->field1);
          printf("field2 = %d\n", bar->field2);
      
          return 0;
      }
      

      另外两个例子来说明按值传递和模拟按引用传递之间的区别。

      考虑以下程序:

      #include <stdio.h>
      
      void foo(int y)
      {
          y = 5;
      }
      
      int main(void)
      {
          int x = 1;
          printf("1: x = %d\n", x);
          foo(x);
          printf("2: x = %d\n", x);
      
          return 0;
      }
      

      上面的程序会打印出来

      1:x = 1 2:x = 1

      这是因为x 中的值的副本 被传递给函数foo。修改foo内部的本地副本不会修改main内部的原始变量x

      现在模拟通过引用传递:

      #include <stdio.h>
      
      void foo(int *y)
      {
          *y = 5;
      }
      
      int main(void)
      {
          int x = 1;
          printf("1: x = %d\n", x);
          foo(&x);
          printf("2: x = %d\n", x);
      
          return 0;
      }
      

      这个程序将打印

      1:x = 1 2:x = 5

      这是因为我们没有改变函数foo中的指针变量y,而是改变了它指向的位置的值,这恰好是main函数中的变量x

      【讨论】:

      • 这真的是一个好习惯吗?我的意思是,返回一个在 initializeFields 中分配的结构指针听起来比在一个指针的指针中分配并且什么都不返回要好得多,在 malloc 失败的情况下甚至不返回错误代码。
      • @Bionix1441 因为 C 只有所谓的按值传递,这意味着为传递的参数创建一个副本。修改副本当然不会修改原件。如果您有一个接受 int 参数的函数,并且在函数中修改了参数,您是否希望在调用中传递给函数的值被修改?
      • @Someprogrammerdude 如果我理解正确的话:修改int我们需要一个指针,修改实际的指针我们需要指向这个指针的指针
      • @Bionix1441 正确。添加了几个例子来展示整数。
      • @Bionix1441 当你想修改作为参数传递的东西时,你需要一个指向那个东西的指针。
      【解决方案3】:

      在某些非常特殊的情况下,您需要指向结构指针(主要是结构指针数组)的指针。

      否则,指向结构的指针就足够了。

      struct someStruct
      {
          int field1;
          int field2;
      }
      
      void initializeFields(struct someStruct* foo)
      {
          foo->field1 = 42;
          foo->field2 = -1;
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-12
        • 1970-01-01
        • 2012-08-20
        • 1970-01-01
        • 1970-01-01
        • 2015-01-24
        • 2013-12-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多