Viewed: 1 - Published at: a few seconds ago

[ Structures and linked list accessing. ]

#include <stdio.h>

int main(void)
typedef struct{ 
    int a;
} cool;

cool x;

(&x)->a = 3;
x.a = 4;

I was wondering if the (&x)-> a does the same thing as the x.a. I coded both of them up, and it seemed that both of them changed the value of x.a. I know it must be a pointer on the left side of ->, but the (&x) seems to work without problem. Printing out x.a works for both of them, and gives me the correct answer. I looked up a lot about pointers, linked list, and structures and am still not able to find out the answer. Would it be possible to get an explanation? Thank you!

Answer 1

The -> operator expects a pointer on the left hand side. &x returns the address of x so it satisfies that requirement (even if it is totally redundant). To think about it another way...

cool *y = x;
y->a = 3;

The . operator expects a stack allocated struct on the left hand side. x is that, so x.a works fine.

You can also go the other way, if you have a pointer y you can dereference it with *y and use . on it: (*y).a. This is also totally redundant.

Answer 2

The & prefix operator returns the memory address of whatever object you put it in front of.

This means that you have to put it in front of objects that actually have a memory address. For example, literals and temporary expression results don't necessarily have an address. Variables declared with register storage class don't have an address, either.


int i = 5;
&i;  // works

&5;  // Nope!

&(i + 1); // Nope!

&i + 1;  // Works, because &i has higher precedence than +1.

So what does the address of an object give you? It is a pointer to the object. This is how you can do dynamic memory allocation using the heap. This is where functions like malloc() come in. And this is how you can build arbitrarily large data structures.

In C, arrays are represented as pointers. So arrays and pointers are often used interchangeably. For example:

char buffer[100];  // array
strcpy(buffer, "hello"); // strcpy is declared to take (char *, const char *)

The opposite of the address_of operator is the * dereference operator. If I declare a pointer to something, I can get "what it points at" using this syntax:

int i = 5;
int *pi = &i;  // pointer to int. Note the * in the declaration?

i + i; // 10
i + *pi;  // Also 10, because pi "points to" i

In the case where you have an aggregate type like a struct or union, you would have to do something like this:

struct {
    int a;
} s;

s.a = 5;

/* ??? */ ps = &s;  // pointer to s

s.a;  // 5

(*ps).a; // Also 5, because ps points to s.

ps->a;  // 5, because a->b is shorthand for (*a).b

This only works, of course, if you have a pointer to an object that CAN use the .member and that has an appropriately named member. For example, you can't do this:

i = 5;
pi = &i;

pi->a;  // WTF? There is no i.a so this cannot work.

If you have a pointer, you can take the address of it. You then have a pointer to a pointer. Sometimes this is an array of pointers, as with the argv array passed to main:

int main(int argc, const char *argv[]);
int main(int argc, const char **argv); // Effectively the same.

You can do weird stuff with pointers to pointers:

int i = 5;
int j = 100;

int * pij;

for (pij = &i; i < j; ) {
    if (i & 1) {
        *pij *= 2;
        pij = &j;
    else {
        i += 1;
        *pij -= 1;
        pij = &i;

Note: I have no idea what that code does. But it's the kind of thing you can wind up doing if you're working with pointers.