2

I am new to c.i read that array subscript operator and pointer arithmetic are interchangeable for access member variable.But in the following code i get error when i used the -> operator for access the member variable i get error .i am bit confuse what is happening under the hood .what am i missing .

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

typedef struct {
        int x, y;
} Point;

int main ()
{
        int numOf;
        Point *myPoints = NULL;
        FILE *myfile = fopen ("c:\\jobs.txt","r");
        if (myfile == NULL)
            perror ("Error opening file");
        else
        {
            fscanf(myfile, "%d", &numOf);
            myPoints = (Point *)malloc(sizeof(Point) * numOf);
            while ( !feof (myfile) && numOf-- )
            {
               fscanf(myfile, "%d %d", &(myPoints+numOf)->x, &myPoints[numOf].y);// compile and works 
               //fscanf(myfile, "%d %d", &myPoints[numOf]->x, &myPoints[numOf].y);// dos not compile or  &(myPoints[numOf])->x
            }
            printf("%d %d \n",myPoints->x,myPoints->y);//compile and works 
        }
        fclose(myfile);
        //Do stuff with array
        free ((void *)myPoints);
        getchar();//Press enter to close debugger etc.
        return 0;
}

is the cases when i use subscript operator i can't use the -> with it . like &myPoints[numOf]->x

Xax
  • 185
  • 6
  • 18
  • 2
    The arrow `->` binds tighter than the `&` address of, so `&myPoints[numOf]->x` is the same as `&(myPoints[numOf]->x)`, which is invalid because `myPoints[numOf]` is a structure and requires a dot `.`, rather than `(&myPoints[numOf])->x`, which would pass `x` to `fscanf()` or `&(&(myPoints[numOf])->x)` which should pass the address of `x` to `fscanf()`. – Jonathan Leffler Apr 21 '15 at 04:48
  • In gcc, It is not showing any error. – Karthikeyan.R.S Apr 21 '15 at 04:50
  • @JonathanLeffler but why &(mypoints+numOf)->x works as (mypoints+numOf) is same as mypoints[numOf]. i am bit confuse can u explain a bit more – Xax Apr 21 '15 at 04:54
  • Remember the star: `*(myPoints+numOf)` is equivalent to `myPoints[numOf]`. – Jonathan Leffler Apr 21 '15 at 04:55
  • @JonathanLeffler `&(&(myPoints[numOf])->x)` is not working also `main.c:22:51: error: invalid type argument of '->' (have 'Point')` – Xax Apr 21 '15 at 05:02
  • I was a bit worried about that. It's damn ugly, that's for sure, and should never actually be written. Let me go experiment with a friendly compiler. – Jonathan Leffler Apr 21 '15 at 05:03
  • Incidentally, you should be checking the return value from `fscanf()` and [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong). – Jonathan Leffler Apr 21 '15 at 05:05
  • Ugh! I got caught by the same problem you did, which was a tad careless. In my defense, I'd never write code like that. This gruesome expression does compile, though: `int *ip04 = &(&(myPoints[numOf]))->x;` where I assigned to an `int *` rather than passing the `int *` to `fscanf()`. – Jonathan Leffler Apr 21 '15 at 05:13
  • @avi Do not cast the return of `malloc`. e.g. `myPoints = (Point *)malloc(sizeof(Point) * numOf);` should simply be `myPoints = malloc(sizeof(Point) * numOf);` or even simpler `myPoints = malloc( sizeof *myPoints * numOf);` – David C. Rankin Apr 21 '15 at 06:11
  • @DavidC.Rankin can you elaborate what would be difference if i not cast to Point . – Xax Apr 21 '15 at 06:20
  • There is NO difference. `malloc` returns a void pointer to the start address for the block of memory allocated. It's not `Point` type or any other type, it's just a memory address. When you cast, you introduce the potential for error that is difficult to debug. You don't need the cast, why make your life harder by doing it? – David C. Rankin Apr 21 '15 at 06:23
  • so why books cast to specific datatypes @DavidC.Rankin. if there is not advantage of casting – Xax Apr 21 '15 at 06:26
  • You will have to ask the ill informed author. Perhaps they were trying to make a point or perhaps it was a limitation on their compiler from **years and years** ago. If you don't want to take my word for it. Search `cast malloc` here on StackOverflow and see what you find... – David C. Rankin Apr 21 '15 at 07:30

1 Answers1

4

Expression myPoints + numOf has type Point * that is a pointer. To access a data member of the object pointed to by the pointer there is used the following syntax

( myPoints + numOf )->x

The address of this data member x can be get using unary operator &. Thus expression

&( myPoints + numOf )->x

gives the address of data member x of the object pointed to by pointer myPoints + numOf.

You could write the above expression like

&( *( myPoints + numOf ) ).x

Because postfix operator . has higher priority than the unary operator * you have to use parentheses.

In fact expression ( *( myPoints + numOf ) ).x is equivalent to expression myPoints[numOf].x. These two forms give the same result. So instead of

&( myPoints + numOf )->x

or

&( *( myPoints + numOf ) ).x

you may write

&myPoints[numOf].x

This record

&myPoints[numOf]->x

is invalid because expression myPoints[numOf] does not yield a pointer. It is an object of type Point itself.

As the priority of postfix subscript operator [] and of -> is higher than the priority of unary operator & then you have to write instead

&( &myPoints[numOf] )->x
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • for `(&myPoints[numof])->x` i got segmentation fault – Xax Apr 21 '15 at 05:32
  • @avi You have to specify the address &(&myPoints[numof])->x – Vlad from Moscow Apr 21 '15 at 05:33
  • can you tell me why using &(&(myPoints[numOf])->x) not working ..also can u suggest some reading so that i can clear myself more on this matter – Xax Apr 21 '15 at 05:38
  • @avi This &(&(myPoints[numOf])->x) does not work because the priority of the postfix operator -> is higher than priority of unary operator &. In fact expression &(myPoints[numOf])->x is equivalent to &(myPoints[numOf]->x ) while you need ( &myPoints[numOf] )->x – Vlad from Moscow Apr 21 '15 at 05:48