【问题标题】:C passing a list as argumentC 将列表作为参数传递
【发布时间】:2013-01-26 13:52:30
【问题描述】:

所以我将列表定义为全局变量:

typedef struct center {

  char center_name[100];

  char hostname[100];

  int port;

  struct center *next_center;

} center;

我需要向列表中添加元素。但是我需要添加的这些元素都在一个文件中,所以:

 int main(int argc, char** argv) {
     center *head = NULL; 
     parse(argv, head);
  }

parse 是一个函数,它读取文件并将这些读取的元素添加到一个新的中心(所有这些都有效,它仔细检查了)

void parser (char** argv, center *head) {
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, head); 
}

地点:

addToCenter(center *newCenter, center *head){
   //adds newCenter to the list
   if (head == null)
      head = newCenter;
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }

}

一切正常,除了 Main 上的列表总是返回为 null。换句话说,引用没有被修改。我不明白为什么,因为我正在传递一个指向列表的指针。

虽然我的另一个解决方案是将列表的头变量创建为全局变量,但最好避免这些情况。

提前致谢。

【问题讨论】:

  • 你已经修改了传入的指针值'head',它在堆栈上。

标签: c list reference


【解决方案1】:

您的列表头正在按值传递。您需要通过 address 传递头指针,以防它被修改(它将被修改)。

例子:

addToCenter(center *newCenter, center *head) // <=== note: passed by value
{
   //adds newCenter to the list
   if (head == null)
      head = newCenter; // <=== note: modified local stack parameter only.
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }
}

应该是:

addToCenter(center *newCenter, center **head) // <=== note: now passed by address
{
   //adds newCenter to the list
   if (*head == null)
      *head = newCenter;  // <=== note: now modifies the source pointer.
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }
}

解析也是如此:

void parser (char** argv, center **head) // <=== again, the head-pointer's *address*
{
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, head);  // <=== just forward it on.
}

最后回到 main:

int main(int argc, char** argv) 
{
     center *head = NULL; 
     parse(argv, &head);  // <=== note: passing address of the head-pointer. (thus a dbl-pointer).
}

【讨论】:

  • 真的很好解释!谢谢,我明白了很多。是的,只要它允许我,我就会接受答案。我忘记了 &,它给了我正在传递的对象的地址。再一次,真的很好解释。
  • @Alessandroempire 不用担心。很高兴这是有道理的。对于刚接触 C 语言的人来说,指针对指针通常是一件很难立即掌握或识别何时需要它的东西,就像在这种情况下一样。这对你来说足够清楚是好的。很乐意提供帮助。
【解决方案2】:

你需要像这样传递它:

void parser (char** argv, center **head) {
   //read the elements i need to add
   //creates a newCenter and adds the elements read to the new center
   //this far it works
  addToCenter(newCenter, &head); 
}

addToCenter(center *newCenter, center **head){
   //adds newCenter to the list
   if (*head == null)
      *head = newCenter;
   else {
      //find last element
      lastelement.next_center = newCenter; 
   }

}

主要是:

int main(int argc, char** argv) {
     center *head = NULL; 
     parse(argv, &head);
}

您必须这样做,因为 C 中的值默认情况下是按值传递的。由于您通过值而不是通过引用传递列表的地址。当您像上面的程序一样通过引用传递变量head 时,您将能够修改列表并将数据返回到列表中。否则,它将按值传递,并且永远不会修改head 的值(因此你得到NULL

【讨论】:

  • @Alessandroempire 它会为您提供要应用它的变量的地址。
  • 是的,C 不是面向对象的语言,所以任何可以被认为是object 的东西实际上都是一个变量(这也是 C++ iMho 的情况,即使它是 OO)
  • 很抱歉,我必须用 C 语言编写一个程序,用 Java 编写另一个程序,所以有时我会把它们搞混。我的坏,但我现在记得。非常感谢
  • @Alessandroempire 没问题 :-) 当您使用一种语言工作并且必须切换到另一种语言时,心理惯性需要时间
【解决方案3】:

将指针传递给函数可以让您看到在函数之外分配指向值的结果。但是,指针本身还是按值传递的。

为了在parseraddToCenter 中修改head,您必须将一个指向head 的指针传递给这两个函数。

void parser(char** argv, centerPtr **headPtr) {
     /* rewrite using *headPtr instead of head */
}
void addToCenter(center *newCenter, center **headPtr) {
     /* rewrite using *headPtr instead of head */
}
int main(int argc, char** argv) {
    ....
    parser(argv, &head);
    ....
}

【讨论】:

    【解决方案4】:

    在您的函数中,您修改的是指针的本地副本,而不是指针本身。您应该更改函数定义以获取指向指针的指针。

    【讨论】:

      【解决方案5】:

      您似乎缺少有关指针逻辑的部分知识。我将尝试描述这里出了什么问题。

      首先,让我们将任何void* 重写为int,这是(在某种程度上)内部发生的事情。

      addToCenter(int newCenter, int head){
         //adds newCenter to the list
         if (head == 0)
             head = newCenter;
      

      到这里,问题就说明了。

      解决方案?

      addToCenter(center *newCenter, center **head){
         //adds newCenter to the list
         if (*head == null)
             *head = newCenter;
      

      【讨论】:

      • 多一点解释会有所帮助。现在还为时过早,“问题说明了自己”只是暂时不适合我。
      猜你喜欢
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-20
      • 2011-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-19
      相关资源
      最近更新 更多