0

I study electronics engineering and I'm learning C as my first language. I've been following IIT C Programming course, and it often takes me a little more time to understand the program when pointers are involved.

I'm learning about linked lists right now, I'll put part of the code then tell you guys what I'm having problem with. I'll not put everything because I don't think it will be necessary.

typedef struct node_type {
    int data;
    struct node_type *next;
} node;

typedef node_type *list;

list head, temp;
char ch;
int n;
head = NULL;
scanf("%c", &ch);

while (ch == 'Y' || ch == 'y') {
    temp = (list)malloc(sizeof(node));
    temp->data = n;
    temp->next = head;
    head = temp;
    scanf("%c", &ch);

I couldn't understand why the use of '->' when working with pointers to structs, I know now that temp->data = n; is equivalent to (*temp).data = n;. But I'm having problem with the syntax of the second expression and why using it gives access to 'data' inside the struct which 'temp' points to.

When declaring variables there's an order as seen here: http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html

I know that there's a precedence order for the operators. In declarations I read * as "pointer to". How should I read (*temp).data in the middle of the code (not declaration) ?

In the beginning of the course, Dr.P.P.Chakraborty says that * could be understand as "the content of", but it wouldn't make sense in this expression: "the content of temp..."

  • What is the meaning of the operator * when not used in declarations?
  • The use of typedef follows the same rule of declarations like int *a[]? typedef int *a[] declares that the type 'a' is an array of pointers to int?

Appreciate any help.

João Pedro
  • 167
  • 6
  • Sounds like you have multiple questions. Can you list out all the questions with a bulleted list? – VHS Mar 23 '17 at 21:59
  • Yes, maybe it will help someone in the future. For now I think I understand the meaning, but I will adjust my question. Thanks. – João Pedro Mar 23 '17 at 22:03
  • If you're using a C compiler and not a C++ compiler, and there are no other headers defining structures, then `typedef node_type *list;` won't compile. You could use `typedef struct node_type *list;` (but [you shouldn't `typedef` pointers](http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers)) and that would compile. – Jonathan Leffler Mar 23 '17 at 22:41
  • And read `(*temp).data` as a tyro's way of writing `temp->data` — petty obfuscation of the code. – Jonathan Leffler Mar 23 '17 at 22:44
  • `typedef node_type *list;`Dont hide pointers behind typedefs. It will confuse you and others. Just dont. – wildplasser Mar 24 '17 at 00:25

2 Answers2

2

The *temp means pointer dereference. So when you write (*temp).data the result of (*temp) has type node and not node*. Thus you can access the structure field using .

Alex
  • 9,891
  • 11
  • 53
  • 87
  • temp is a pointer and dereference means to get access to what temp points to? If that's correct maybe it's better to forget about "the content of"... – João Pedro Mar 23 '17 at 22:02
  • 1
    @JoãoPedro, More precisely it is "the content of the memory pointed by ...". – Alex Mar 23 '17 at 22:04
  • 3
    You may also see the notation temp->data which is equivalent to (*temp).data and both dereference the pointer temp to locate the struct stored there, and then retrieve the value of data. – ScottK Mar 23 '17 at 22:06
1

I know that there's a precedence order for the operators. In declarations I read * as "pointer to". How should I read (*temp).data in the middle of the code (not declaration) ?

"Retrieve the data member of the struct node_type instance that temp points to".

Graphically:

      +---+        +---+
temp: |   |----->  |   | data <--- I want this
      +---+        +---+
                   |   | next
                   +---+

But I'm having problem with the syntax of the second expression and why using it gives access to 'data' inside the struct which 'temp' points to.

The expression temp has type "pointer to struct node_type". The unary * operator dereferences the pointer to access the pointed-to object. Thus, the expression *temp has type struct node_type.

Assume the following declarations:

struct node_type instance;
struct node_type *pointer = &instance;

After both declarations are complete, the following expressions are true:

 pointer == &instance;    // struct node_type * == struct node_type *
*pointer ==  instance;    // struct node_type   == struct node_type

 pointer->data == (*pointer).data == instance.data; // int == int == int
 pointer->next == (*pointer).next == instance.next; // struct node_type * == struct node_type *

Both of the member selection operators . and -> are grouped with the postfix operators, which have higher precedence than unary * - had you written *temp.data, the compiler would have parsed it as *(temp.data), which would mean "I want the thing that temp.data points to."

Graphically:

      +---+              +---+
temp: |   | data ------> |   | <--- I want this
      +---+              +---+
      |   | next
      +---+

That's not what you want in this particular case.

As you discovered, temp->data is equivalent to (*temp).data - the -> operator implicitly dereferences the temp pointer. When dealing with pointers to struct and union types, you really want to use -> - it's less eye-stabby, and you're less likely to make a mistake with it.

Other places to watch out for precedence issues with pointers:

T *a[N];   // a is an N-element array of pointers to T

Graphically:

   +---+            +---+
a: |   | a[0] ----> |   | some instance of T
   +---+            +---+
   |   | a[1] --+
   +---+        |   +---+
    ...         +-> |   | some other instance of T
                    +---+

Each a[i] points to a distinct object of type T. To access the object, you'd dereference the array element - *a[i].

T (*a)[N]; // a is a pointer to an N-element array of T

Graphically:

   +---+        +---+
a: |   | -----> |   | (*a)[0]
   +---+        +---+
                |   | (*a)[1]
                +---+
                 ---

To access elements of the array, you need to deference the pointer a before you apply the subscript - you want to index into the thing a points to, so you need to write (*a)[i].

T *f();   // f is a function returning a pointer to T

The function f returns a pointer value; to access the thing being pointed to, you'd need to deference the return value:

x = *f();

Note that this is rarely done; you always want to do a sanity check on returned pointer values. You're far more likely to see:

T *p = f();
if ( p )
  x = *p;

And finally,

T (*f)(); // f is a pointer to a function returning T

f points to a function - you must dereference f itself in order to execute the function:

x = (*f)();

You can get a clue of how to use each version of a and f based on its declaration.

John Bode
  • 119,563
  • 19
  • 122
  • 198