2

I see a piece of code like this:

#include<stdio.h>
struct person{
   int age;
   float weight;
};
int main(){
   struct person *personPtr, person1;
   personPtr = &person1;
   printf("Enter age: ");
   scanf("%d", &personPtr->age); // why use &personPtr->age, shouldn't it just be personPtr->age since personPtr is itself a pointer. 
   printf("Enter weight: ");
   scanf("%f", &personPtr->weight); // similarly here: should it be personPtr->weight instead. Why the & in front of personPtr, I thought & means address, so wouldn't it means address of the pointer which seems wrong here if we want to show the weight value. 
   printf("Displaying:\n");
   printf("Age: %d\n", personPtr->age);
   printf("weight: %f", personPtr->weight);
   // however if I do: printf("weight: %f", &personPtr->weight); this doesn't print the value of weight. So it has to do with the scanf function? 
   return 0;
}

the thing I don't understand is what are the difference between: &personPtr->age and personPtr->age

in the code above. I always see peresonPtr->age type of codes when I have a pointer to a struct and want to retrieve the inner variable of that struct.

So say I have a struct

struct A {
   int x;
   int y;
};

struct A f1;
struct A *f2 = &f1;

then I know I can do:

f2->x, f2->y to get the value of x, and y of the x, y variables inside the struct f1. But what does &f2->x, &f2->y?

Or the use of & in &personPtr->age has to do with the scanf function here? (because its use & inside the scanf function here.

could someone explains the difference and why use the &personPtr->age instead of personPtr->age.

Another example here, for example here in the Mutex function, I again see the &


uthread_mutex_t uthread_mutex_create () {
  uthread_mutex_t mutex = malloc (sizeof (struct uthread_mutex));
  mutex->holder = 0;
  mutex->reader_count = 0;
  spinlock_create   (&mutex->spinlock); \\ why &mutex, instead of just mutex?????
  uthread_initqueue (&mutex->waiter_queue);
  uthread_initqueue (&mutex->reader_waiter_queue);
  return mutex;
}

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
hodondo
  • 83
  • 1
  • 5

2 Answers2

0

personPtr is a pointer to the whole object person1

personPtr = &person1;

So this expression personPtr->age yields the data member age of the object person1 which you need to pass to scanf by reference that is through a pointer to it

scanf("%d", &personPtr->age);

To make it more clear you may rewrite the expression like

scanf("%d", &( personPtr->age ));

That is the expression &( personPtr->age ) yields the address of the data member age of the object person1. And the function scanf expects as its argument a pointer to the original object. Thus dereferencing the pointer the function will get a direct access to the original object (instead of a copy of the value of the object) that can be changed such a way.

Also consider the following demonstration program.

#include <stdio.h>

void f( int x )
{
    x = 10;
}

void g( int *px )
{
    *px = 10;
}

int main( void )
{
    int x = 0;

    printf( "Before calling f() x = %d\n", x );

    f( x );

    printf( "After  calling f() x = %d\n", x );

    printf( "Before calling g() x = %d\n", x );

    g( &x );

    printf( "After  calling g() x = %d\n", x );
}

The program output is

Before calling f() x = 0
After  calling f() x = 0
Before calling g() x = 0
After  calling g() x = 10

As the function g accepts the variable x by reference (&x) then dereferencing the pointer it can change the original variable x. On the other hand, the function f deals with a copy of the value of the original variable x. So changing the copy has no influence on the original variable x.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

In C scanf() requieres a pointer to be passed to it. Because personPtr is a pointer to a person struct,simply passing it personPtr->age would give scanf the value of person1's age field and not a pointer to it and so the compiler would complain that scanf requieres a pointer but was passed an integer.

By doing &personPtr->age you are passing scanf the address of the age field from person1. Because you passed it an address and not an integer this time, there is no compilation error.

then I know I can do:

f2->x, f2->y to get the value of x, and y of the x, y variables inside the struct f1. But what does &f2->x, &f2->y?

&f2->x, &f2->y would give you the address of the x and y fields respectively. In contrast, f2->x, f2->y would give you their values.

Similarly in your last example,

uthread_mutex_t mutex = malloc (sizeof (struct uthread_mutex));

because malloc returns a pointer to the start of the allocated chunk of memory, mutex is simply a pointer to an uninitialized uthread_mutex struct.

The function

spinlock_create(&mutex->spinlock);

takes a pointer as it's argument. That's why you must pass it &mutex->spinlock or formatted differently: &(mutex->spinlock).

The same applies for the functions uthread_initqueue(); and uthread_initqueue();

MottLx
  • 53
  • 1
  • 7