简体   繁体   English

c - 如何访问从指针到指针的值?

[英]How to access values from pointers to pointers in C?

I am writing a program that is attempting to implement a hash table in C. It has to use a pointer to a pointer as an attribute in a struct data type.我正在编写一个试图在 C 中实现哈希表的程序。它必须使用指向指针的指针作为结构数据类型中的属性。 Here is the code of the relevant structs.这是相关结构的代码。

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

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

Part one of question:问题的第一部分:

I have been doing a lot of research to figure out just how pointers to pointers work but I still can't seem to get my head around it.我一直在做很多研究来弄清楚指向指针的指针是如何工作的,但我似乎仍然无法理解它。 Every example I've found assigns two different pointer names to the first and second pointer.我发现的每个示例都为第一个和第二个指针分配了两个不同的指针名称。 eg例如

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

What about the case above "struct node ** table;"上面的例子“struct node ** table;”怎么样? Is ** table the same as **q in this case?在这种情况下,** 表是否与 **q 相同? What would the values of q , *q and **q be in this case?在这种情况下 q 、 *q 和 **q 的值是什么? is q = 5 and then *q and **q work back through the addresses or is **q = 5 and *q and q store the addresses?是 q = 5 然后 *q 和 **q 返回地址还是 **q = 5 和 *q 和 q 存储地址?

Part two of question:问题的第二部分:

How do I access a pointer to a pointer within another function?如何访问指向另一个函数内的指针的指针? Here is the code I have right now.这是我现在拥有的代码。

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;
    }

};

I'm not sure I understand how to access either the pointer or the pointer to a pointer through the -> symbol.我不确定我是否理解如何通过 -> 符号访问指针或指向指针的指针。 Is it "newtable -> table" or "newtable -> -> table" ?是“newtable -> table”还是“newtable -> -> table”?

The aim of the table is essentially to be a 2d table, where the list is primarily 1D and can spread to 2D to deal with collisions in the hashing.该表的目标本质上是一个 2d 表,其中列表主要是 1D 并且可以扩展到 2D 以处理散列中的冲突。

End note:尾注:

Hopefully I've provided enough information to make contextual sense asking this question.希望我已经提供了足够的信息来使提出这个问题的上下文有意义。 Its my first time asking a question on stackoverflow so feel free to ask me extra question, provide CC or flag any mistakes I've made asking this question.这是我第一次在 stackoverflow 上提问,所以随时问我额外的问题,提供 CC 或标记我在问这个问题时犯的任何错误。

Thank you!谢谢!

There are several ways to look at a pointer to a pointer.有几种方法可以查看指向指针的指针。 One way is as you described with一种方法是如您所描述的

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

After all that, the following are all true:毕竟,以下都是正确的:

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

However, another way to look at a pointer to a pointer is as an array of pointers.但是,另一种查看指向指针的指针的方式是将指针视为数组 For example, assume the declaration:例如,假设声明:

int *arr[10];

Except when it is the operand of the sizeof or unary & operands, the expression arr will be converted ("decay") from type "10-element array of int * " to "pointer to int * ", or int ** .除非它是sizeof或一元&操作数的操作数,否则表达式arr将从类型“ int * 10 元素数组”转换(“衰减”)到“指向int *指针”或int **

If you want to dynamically allocate an N -element array of pointers to struct node , you would write如果你想动态分配一个N元素的指针数组到struct node ,你会写

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

You would use the [] subscript operator to access elements in arr as you would a normal array.您可以像访问普通数组一样使用[]下标运算符访问arr元素。 Since arr has type struct node ** , each arr[i] has type struct node * , so you would access members of the structure like so:由于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 allows you to create multiple hashtable instances, each one of which has a size member and an array of struct node * which you allocate at runtime, like so: 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
}

You'd insert a new element into the table like so:您可以像这样在表中插入一个新元素:

/**
 * 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.
}

When you're done, your hashtable looks something like this:完成后,您的哈希表如下所示:

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

table points to an array of struct node * , each of which may point to an instance of struct node , each of which may point to another instance of struct node . table指向一个struct node *数组,每个数组可能指向一个struct node实例,每个都可能指向另一个struct node实例。 In the picture above, two strings have hashed to table[0] , one to table[2] , and three to table[3] .在上图中,两个字符串散列到table[0] ,一个散列到table[2] ,三个散列到table[3]

Here's a little program that might help you, it might be worth playing about with pointers for a bit and inspecting them, output addresses etc.这是一个可能对您有所帮助的小程序,它可能值得玩一会儿指针并检查它们,输出地址等。

#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);
    }

Hope this helps.希望这可以帮助。

As for referencing the struct from another function, if you're passing a pointer to that structure you use a single -> to refer to any member of the struct...but you are allocating another struct within your struct - using a pointer.至于从另一个函数引用结构,如果您将指针传递给该结构,则使用单个 -> 来引用结构的任何成员……但是您正在结构中分配另一个结构 - 使用指针。

Say I have说我有

struct one {
    char *string;
}

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

If have a pointer to a struct two:如果有一个指向结构二的指针:

struct two *t;结构二 *t;

And it had its member a allocated a struct one...then I'd reference the members of a using ->并且它的成员 a 分配了一个结构体...然后我会引用一个 using ->

t -> a -> string;

But b isn't a pointer so you would do:但 b 不是指针,所以你会这样做:

t -> b.string;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM