2

Can someone explain this for loop to me?

struct {
  int lock;   // not used in Lab
  struct proc proc[NPROC];
} ptable;

void scheduler(void){
struct proc *p;

  acquire(&ptable.lock);
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
    if(p == curr_proc || p->state != RUNNABLE)
      continue;

    // Switch to chosen process.
    curr_proc = p;
    p->state = RUNNING;
    break;
  }
  release(&ptable.lock);

}

Mostly I'm asking about the for loop

  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){

What does assigning the pointer p to ptable.proc do? And how do I access the struct proc's members/variables?

4
  • 1
    Does this answer your question? What is array to pointer decay? Commented Oct 4, 2022 at 19:06
  • 1
    What Stephen Newell said. And you access struct proc's variables like you actually do in your code: p->state. Commented Oct 4, 2022 at 19:10
  • 1
    When a for loop is hard to undestand, writing it as a while loop may make understanding easier. Commented Oct 4, 2022 at 19:12
  • 1
    What does assigning the pointer p to ptable.proc do?. It makes p point to ptable.proc. IOW, the value of p is now the address of ptable.proc[0]. Incrementing p makes the value of p be the address of ptable.proc[1]. Commented Oct 4, 2022 at 19:18

3 Answers 3

2

Mostly I'm asking about the for loop

for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
p = ptable.proc

Here the array ptable.proc decays into a pointer to the first element in the array and p is assigned this pointer. It's the same as doing p = &ptable.proc[0].

p < &ptable.proc[NPROC]

Here p is compared with the address one element outside the array bounds (out of bounds). ptable.proc[NPROC - 1] is the last element within bounds.

p++

This steps the pointer to point at the next struct proc in the struct proc array.

So, the for-loop as a whole starts by making p point at the first struct proc in the array and iterates through all the elements in the array until p points outside the array, then it terminates the loop.

Here's an alternative loop with the same result to visualize what's going on:

// for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
for(int idx = 0; idx < NPROC; idx++) {
    p = &ptable.proc[idx];   // or:   p = ptable.proc + idx;

    // the rest of the loop body goes here ...
}

And how do I access the struct proc's members/variables?

You dereference the pointer p with the -> operator to access the members of the element p is pointing at. p->state accesses the state member in the struct proc that p is currently pointing at.

Sign up to request clarification or add additional context in comments.

Comments

1

p = ptable.proc assigns a pointer to the start of the array to p.

The array contains NPROC elements so &ptable.proc[NPROC] is the (notional) address of one past the last element (ptable.proc[NPROC-1] is the last element). ptable.proc+NPROC would be cleaner.

p++ increments the pointer by the size of one struct proc.

The net effect is a pointer starts at the beginning of the array a progress up through it moving sizeof(struct proc) bytes each time visiting each element of the array until it passes the end and immediately stops.

It may look complicated but in C it is the most efficient and natural way to iterate through an array.

Comments

1

If you have an array as for example like

enum { N = 10 };
int a[N] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

then you can access its elements using the subscript operator like for example

for ( int i = 0; i < N; i++ )
{
    printf( "%d ", a[i] );
}
putchar( '\n' );

The subscript operator is evaluated like

a[i] ==> *( a + i )

But if you have a pointer to the i-th element of the array like

int *p = &a[i];

then instead of the expression a[i] you can just use the expression *p to get the value of the i-th element of the array.

Initially you can initialize the pointer p by the address of the first element of the array

int *p = &a[0];

that is equivalent to

int *p = a;

because in this case the array is implicitly converted to pointer to its first element.

So the expression *p yields the first element a[0] of the array. To output the second element of the array you could write for example p[1] that is equivalent to *( p + 1 ).

But the expression p + 1 yields the same value as the expression ++p because the expression ++p is evaluated like p = p + 1.

So you can write to output the first element of the array

printf( "%d ", *p );

To output the second element of the array you could write

printf( "%d ", *++p );

or

++p;
printf( "%d ", *p );

and so on.

Thus the above for loop can be rewritten using a pointer the following way

for ( int *p = a; p < a + N; ++p )
{
    printf( "%d ", *p );
}
putchar( '\n' );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.