-1

I am trying to understand why this 3rd argument in the scanf() function needs an ampersand but not the 2nd one, without the ampersand I get an error saying "Argument 3 of scanf() is not a pointer".

struct person {
    int age;
    float weight;
    char name[30];
};
for(i = 0; i < n; ++i)
   {
       printf("Enter name of person %d and age respectively: ", i);

       // To access members of 1st struct person,
       // ptr->name and ptr->age is used

       // To access members of 2nd struct person,
       // (ptr+1)->name and (ptr+1)->age is used
       scanf("%s %d", (ptr+i)->name, &(ptr+i)->age);
   }

I just want to understand why that's happening and I can't really get the grasp of the arrow pointer operator as well.

  • 1
    What is the definition of that structure? I'm guessing you have a `char*` (already a pointer) and `int` (not a pointer). – tadman Oct 25 '22 at 13:48
  • 1
    Tip: Don't use wonky pointer math when `ptr[i]` is literally *right there*. Also `ptr` is a pretty weak name for a variable, it communicates almost nothing. It's better to have some kind of meaningful label that indicates, or hints at type. – tadman Oct 25 '22 at 13:48
  • This wasn't done by me. It was done by a teacher. I'll edit the definition of the structure in the post. – TaProgrammatizw Oct 25 '22 at 13:50
  • Teachers often some of the singularly *worst* code imaginable, so be sure to take all their advice with a healthy dose of skepticism. – tadman Oct 25 '22 at 13:51
  • I just can't understand why when I remove the & from the 3rd argument I get the error "Argument 3 of scanf() is not a pointer". I don't see any * in the struct so why is the 2nd argument a pointer but not the 3rd one? – TaProgrammatizw Oct 25 '22 at 13:53
  • Arrays (eg: `(ptr+i)->name`) decay to pointers. – Paul Hankin Oct 25 '22 at 13:58
  • 1
    How `%s` works is usually covered very early on in any beginner-level learning material. SO is not an interactive tutorial and besides this question has likely already been asked a thousand times before. – Lundin Oct 25 '22 at 14:20

1 Answers1

1

When you remove the pointer dereferencing, you get something akin to this:

int age;
char name[30];

scanf("%s %d", name, age);

Where clearly the age argument is just an int, and that can't be mutated.1 scanf needs to be able to alter that, so the C convention for a mutable argument is to pass it in as a pointer, or &age in this case.

When extended to your original example you get &(ptr[i]->age), something that can be expressed as a more relaxed &ptr[i]->age since both [] and -> have higher precedence than &.

--

1 Modifications to argument values are local. Modifications made via a pointer impact the original value.

tadman
  • 208,517
  • 23
  • 234
  • 262