【问题标题】:How to access values from pointers to pointers in C?如何在C中访问从指针到指针的值?
【发布时间】:2016-02-20 20:27:03
【问题描述】:

我正在编写一个程序,它试图在 C 中实现哈希表。它必须使用指向指针的指针作为结构数据类型中的属性。这是相关结构的代码。

      struct node {
      char * data;
      struct node * next;
    };

    struct hashtable {
      int size;
      struct node ** table;
    };

问题的第一部分:

我一直在做大量的研究来弄清楚指针的指针是如何工作的,但我似乎仍然无法理解它。我发现的每个示例都为第一个和第二个指针分配了两个不同的指针名称。例如

  x = 5;
  *p = &x;
  **q = &p; 

“struct node ** table;”上面的情况呢? 在这种情况下,** table 是否与 **q 相同? 在这种情况下 q 、 *q 和 **q 的值是多少?是 q = 5 然后 *q 和 **q 通过地址返回还是 **q = 5 并且 *q 和 q 存储地址?

问题的第二部分:

如何访问指向另一个函数中的指针的指针?这是我现在拥有的代码。

struct hashtable * hashtable_new(int size){

    struct hashtable *newTable;

    if ( size < 1 )
    {
        return NULL;
    printf("Its returning Null.");
    }
    else
    {
        newTable = malloc(sizeof(struct hashtable));
        newTable -> size = size;
        newTable -> table = malloc(sizeof(struct node) * size);
        int i;
        for (i = 0; i < size; i++ )
        {

            newTable -> table[i] = NULL;
        }
    fprintf(stderr, "Table has been created.");
        return newTable;
    }

};

我不确定我是否理解如何通过 -> 符号访问指针或指向指针的指针。是“newtable -> table”还是“newtable -> -> table”?

该表的目的本质上是一个 2d 表,其中列表主要是 1D 并且可以扩展到 2D 以处理散列中的冲突。

尾注:

希望我已经提供了足够的信息,以便在提出这个问题时理解上下文。这是我第一次在 stackoverflow 上提问,所以请随时问我额外的问题,提供 CC 或标记我在问这个问题时犯的任何错误。

谢谢!

【问题讨论】:

    标签: c arrays function pointers memory


    【解决方案1】:

    有几种方法可以查看指向指针的指针。一种方法是你用

    描述的
    int   x =  5;
    int  *p = &x;
    int **q = &p; 
    

    毕竟,以下都是正确的:

    **q == *p ==  x == 5
     *q ==  p == &x
      q == &p
    

    然而,查看指向指针的指针的另一种方法是作为指针的数组。例如,假设声明:

    int *arr[10];
    

    除非它是sizeof 或一元&amp; 操作数的操作数,否则表达式arr 将从类型“int *”的10 元素数组类型转换(“衰减”)为“指向int *",或int **。

    如果你想动态分配一个N-element 指向struct node 的指针数组,你可以这样写

    struct node **arr = malloc( sizeof *arr * N );
    

    您可以像访问普通数组一样使用[] 下标运算符来访问arr 中的元素。由于arr 的类型为struct node **,每个arr[i] 的类型为struct node *,因此您可以像这样访问结构的成员:

    arr[i]->data = "foo"; // use -> when the LHS is a pointer to a struct or union
    arr[i]->next = NULL;
    

    struct hashtable 允许您创建多个哈希表实例,每个实例都有一个 size 成员和一个 struct node * 数组,您可以在运行时分配它们,如下所示:

    struct hashtable h1;
    
    h1.size = 512;
    h1.table = calloc( h1.size, sizeof h1.table ); // calloc initializes all elements of
                                                   // h1.table to NULL
    if ( !h1.table )
    {
      // calloc call failed, handle as appropriate
    }
    

    您可以像这样在表格中插入一个新元素:

    /**
     * Assumes we know that the string data points to is not already in
     * the table.  hashfunc is a pointer to the hashing function.
     */
    void insert( struct hashtable *h, const char *data, size_t (*hashfunc)(const char *))
    {
      /**
       * Create a new table entry.  Remember that table is an array of
       * *pointers* to struct node, and that each array element is initially
       * NULL.  We still need to allocate something for that table entry
       * to point *to*.
       */
      struct node *newNode = malloc( sizeof *newNode );
      if ( !newNode )
      {
        /**
         * Memory allocation for new node failed, handle as appropriate
         */
      }
    
      newNode->data = malloc( strlen( data ) + 1 );
      strcpy( newNode->data, data );
    
      /**
       * Get the table index by computing the hash and modding against the
       * table size.
       */
      size_t idx = hashfunc( data ) % h->size;
    
      /**
       * Insert newNode at the head of the list starting at
       * h->table[idx].  In reality you'd probably want to insert 
       * strings in order, but for a toy example this is good enough.
       */
      newNode->next = h->table[idx]; // newNode->next points to the previous head of list
      h->table[idx] = newNode;       // newNode becomes new head of list.
    }
    

    完成后,您的哈希表如下所示:

        +---+
    h1: |   | size
        +---+             +---+     +---+---+     +---+---+
        |   | table ----> |   | --> |   |   | --> |   |   |
        +---+             +---+     +---+---+     +---+---+
                          |   | 
                          +---+     +---+---+
                          |   | --> |   |   |
                          +---+     +---+---+     +---+---+     +---+---+
                          |   | --> |   |   | --> |   |   | --> |   |   |
                          +---+     +---+---+     +---+---+     +---+---+
                           ...
    

    table 指向struct node * 的数组,每个数组都可以指向struct node 的一个实例,每个数组都可以指向struct node 的另一个 实例。在上图中,两个字符串已经散列到table[0], 一个给table[2],三个给table[3]。

    【讨论】:

      【解决方案2】:

      这是一个可能对您有所帮助的小程序,它可能值得玩一下指针并检查它们,输出地址等。

      #include <errno.h>
      #include <stdio.h>
      #include <stdlib.h>
      
      int
      main(void)
          {
              char    *p1 = "String of text.";
              char    **p2;
      
              /**
               * We can print the avtual address of *p1 and **p2...
               */
              fprintf(stdout, "p1 = %p\n", p1);
              fprintf(stdout, "p2 = %p\n", p2);
      
              /**
               * Now if we point p2 at p1 we can then check what address
               * *p2 points at...
               */
              p2 = &p1;
              fprintf(stdout, "*p2 = %p\n", *p2);
      
              /**
               * So if you think about it, *p2 should be the same at p1
               * if we print it as a string:
               */
              fprintf(stdout, "p1 is %s\n*p2 is %s\n", p1, *p2);
      
              exit(EXIT_FAILURE);
          }
      

      希望这会有所帮助。

      至于从另一个函数引用结构,如果你传递一个指向该结构的指针,你使用一个 -> 来引用结构的任何成员......但是你在你的结构中分配另一个结构 - 使用一个指针。

      说我有

      struct one {
          char *string;
      }
      
      struct two {
          struct *one a;
          struct one b;
          char *whatever;
      }
      

      如果有一个指向结构二的指针:

      结构两个 *t;

      它的成员 a 分配了一个结构体...然后我会引用 a 的成员 using ->

      t -> a -> string;
      

      但是 b 不是指针,所以你会这样做:

      t -> b.string;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多