tags:

views:

113

answers:

6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct dict_pair {
  void *key;
  void *value;
  struct dict_pair *tail;
} dict;


dict* NewDictionary(void) {
  dict *dictionary = malloc(sizeof(dict)); //or we can malloc(sizeof(struct dict_pair))
  dictionary->tail = NULL;
}

//dict operations
void put(dict *dictionary, void *key, void *value) {
  //new pair
  dict *new_pair = malloc(sizeof(dict));
  new_pair->key = key;
  new_pair->value = value;
  //chaining
  new_pair->tail = NULL;
  dict *last_node = dictionary;
  while (last_node->tail != NULL) {
    last_node = last_node->tail;
  }

  last_node->tail = new_pair;
}

void* get(dict *dictionary, void *key) {
  dict *current_dict = dictionary;
  while (1) {
    if (current_dict->key == key) {
      return current_dict->value;
    }
    else if (dictionary->tail != NULL) {
      current_dict = current_dict->tail;
    } else break;
  }
  return NULL;
}
//end operations

int main(void) {
  dict *dictionary = NewDictionary();
  put(dictionary,(void *) "buffer1",(void *) "Fake1");
  put(dictionary,(void *) "buffer2",(void *) "Fake2");
  put(dictionary,(void *) "key",(void *) "This is the value.");
  char *result = (char *) get(dictionary, (void *) "key");
  printf("%s\n",result);
}

So I managed to write the above code to implement a dictionary. While I was able to write the code and compile and get it to work expectedly, there are some stuff which I am not clear about. Mostly regarding pointers:

dict *current_dict = dictionary;

Lets take this line for example. We are declaring a variable which holds dict type. current_dict is a pointer, right? and dictionary is a pointer. However, *current_dict is not a pointer, how can it be assigned to a pointer?

Or do I have to explicitly type this to make it error?

dict (*current_dict) = dictionary;

If so, would this mean that the above line mean that we are declaring a current_dict variable with a dict type, and it is a pointer. Wouldnt that declaration be

(dict*) current_dict = dictionary;

As you can see, the spacing and positioning is confusing me.

Can someone help with explaining the difference in the * positioning?

Thanks!

+1  A: 

It doesn't matter where * stands in a variable declaration. dict* current and dict *current are the same. But if you use a pointer in an expression then *dict means dereferencing, that is, it returns an object pointed by dict.

Dmitry
This is not perfectly accurate. It does matter where the * stands, if you declare multiple variables in a single statement. So dict* current, other would create two pointers to dict, where dict *current, other would create one pointer and one variable containing the struct.
frenetisch applaudierend
I don't think it is true. dict *current, other still declares a pointer and a value. dict *current, *other declare two pointers.
Dmitry
Dmitry is right, the first comment is absolutely not true.
caf
I just checked it and you are right. I was sure dict* current, other; would create two pointers, but gcc proved me wrong. Sorry for the misinformation!
frenetisch applaudierend
+2  A: 
dict *current_dict;

is a pointer, whitespace is not significant here. All these definitions are similar:

dict *current_dict;
dict* current_dict;
dict * current_dict;
dict*current_dict;

In all the above cases, current_dict is of type pointer to dict

Be aware, if you have something like this:

dict * current_dict,other_dict;

You have declared 2 variables; current_dict is of type pointer to dict while other_dict is of type dict

nos
+2  A: 
// * to the right of a type means a pointer of that type
Dict* dictPtr1 = dictPtr2; // LHS and RHS are pointers
Dict* dictPtr4 = (Dict *) malloc( sizeof(Dict));

// * to the left of a variable means dereference that variable
// the variable must be a pointer
Dict dictObject = *dictPtr; // LHS and RHS are objects


// & to the left of a variable means the address-of the object
Dict* dictPtr3 = &dictObject;
Phillip Ngan
+6  A: 

While dict *dictionary and dict* dictionary have the same meaning in C, I prefer the former.

I prefer to think of pointer declarations in these terms:

int   x; //  x is an int
int  *y; // *y is an int
int **z; //**z is an int

If you remember that *y is the object that y points to, then it follows that y must be a pointer-to-an-int. And similarly z must be a pointer-to-a-pointer-to-an-int.

Artelius
+1, harder to make mistakes this way.
Carl Norum
A: 

dict *current_dict = dictionary;

Lets take this line for example. We are declaring a variable which holds dict type. current_dict is a pointer, right? and dictionary is a pointer. However, *current_dict is not a pointer, how can it be assigned to a pointer?

This declares current_dict to be a pointer to a dict and sets it to point to the same place that dictionary points to. The positioning of * is only relevant when you declare multiple variables on the same line.

Had you put

dict current_dict = dictionary;

this would not have worked correctly because this declares current_dict to be the actual struct.

For what it's worth, in your put function there is no reason to do

dict *last_node = dictionary;

and then use last_node rather than dictionary. They are both pointers to the same thing and when you declare a pointer in your function parameters as you did with dict *dictionary your function is actually getting a local copy of the pointer from the calling function. Changes to the local copy of the pointer in dictionary will not affect the pointer in the calling function (if you wanted such a thing you'd need to have a function declaration like void put(dict **dictionary, void *key, void *value)... but you don't want that here. :) ).

mcl
+4  A: 

When you write:

dict * current_dict = dictionary;
this is equivalent to:
dict * current_dict;
current_dict = dictionary;

I understand your confusion, because * is used for two purposes in the C language: One purpose is to declare a pointer in a declaration. The second purpose is to dereference a pointer in an expression.

Your example is a declaration on the left side of the equal sign and an expression on the right side of the equal sign. (Technically it's all a declaration which contains an expression, but that muddies the point of why * means a particular thing in a particular context.)

Heath Hunnicutt