3

I've read about it and I mostly get it, but this situation confused me a bit. Why don't we use arrow operator -> in scanf? I understand that dot is used for objects and arrow for pointers but here, g is a pointer to structure.

DOCUMENT *take(int *pn){
        DOCUMENT *g;
        printf("How much documents? ");
        scanf("%d", pn);
        g = (DOCUMENT *)calloc(*pn, sizeof(DOCUMENT));
        for (int i = 0; i < *pn; i++)
        {
            printf("Type in author, name of document and number of pages: ");
            scanf("%s %s %d", g[i].author, g[i].name, &g[i].s );
        }
        return g;
    }
dbush
  • 205,898
  • 23
  • 218
  • 273
qu4lizz
  • 317
  • 2
  • 12
  • Read [*Modern C*](https://modernc.gforge.inria.fr/) and see [this C reference](https://en.cppreference.com/w/c). If you replace `g[i].author` with `g[i]->author` your code won't compile. Use [GCC](http://gcc.gnu.org/) as `gcc -Wall -Wextra -g` – Basile Starynkevitch Jan 26 '21 at 12:56
  • Does this answer your question? [What is the difference between the dot (.) operator and -> in C++?](https://stackoverflow.com/questions/1238613/what-is-the-difference-between-the-dot-operator-and-in-c) – costaparas Jan 26 '21 at 12:57

4 Answers4

6

The array index operator [] has a dereference built into it.

g[i] is exactly the same as *(g + i). So g[i] refers to a DOCUMENT, not a DOCUMENT * and thus you use the member access operator . instead of the pointer-to-member operator ->.

dbush
  • 205,898
  • 23
  • 218
  • 273
2

If the left operand of the . or -> is a pointer, then you use ->. Otherwise if it is an object (plain variable), then you use ..

In this case g[i] is taking a pointer and doing array subscripting on it. The result of that is an object ("lvalue"), not a pointer, hence g[i]..


Also note operator precedence in expressions like &g[i].s. The array subscripting operator [] and the struct member operator . have same operator precedence - they belong to the same group of postfix operators. But that group has left-to-right operator associativity so [] takes precedence over the .. Then after those two follow &, the unary address operator, with lowest operator precedence in the expression. So operator precedence guarantees that the expression is equivalent to &((g[i]).s).

Lundin
  • 195,001
  • 40
  • 254
  • 396
1

The subscript operator used with a pointer yields the object pointed to by the pointer expression. That is, for example, this expression

g[i].author

(where g[i] is the i-th element of the array of structures) is equivalent to

( g + i )->author

where g + i is a pointer that points to the i-th element of the array of structures.

The subscript operator g[i] is equivalent to the expression *( g + i ).

You may write

g[i].author

or like

( *( g + i ) ).author

or like

( g + i )->author

Thus this call of scanf

scanf("%s %s %d", g[i].author, g[i].name, &g[i].s );

can be rewritten like

scanf("%s %s %d", ( g + i )->author, ( g + i )->name, &( g + i )->s );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

When you write g[i], this is actually equal to *(g + i). That is, you dereference the pointer and it becomes an object again, so you can access it with dot (.) instead of arrow (->).

Alex
  • 358
  • 1
  • 11