0

I would like to pass a struct to a function by reference, create a new instance of a struct, destroy the original and return a new struct correctly. A specific example of such case is a queue resize function:

A queue structure itself:

// Queue for storage of pairs
typedef struct {
    int n;        // size of queue
    int m;        // no. of pairs in queue
    int f;        // index of front element
    int r;        // index of rear element
    pair *pairs;  // array of pairs
} queue;

Queue initialisation routine:

// Initialises queue
int init(int const *n, queue *q) {

    q->n = *n;
    q->m =  0;
    q->f =  0;
    q->r =  0;

    q->pairs = (pair*) calloc(q->n, sizeof(pair));

    return 0;
}

Queue destruction routine:

// Destroys queue
int destroy(queue *q) {

    q->n = 0;
    q->m = 0;
    q->f = 0;
    q->r = 0;
    free(q->pairs);

    return 0;
}

Enqueue routine:

// Adds pair to queue
int enqueue(pair *p, queue *q) {

    // resize queue if necessary
    if (isfull(q))  int status = resize(q);

    if (q->m > 0)  q->r = (++q->r) % q->n;
    q->pairs[q->r] = *p;
    q->m++;

    return 0;
}

My take at the queue resizing routine (currently it crashes with a floating point exception). I believe to resize a queue correctly I need to pass a pointer to a queue pointer, but so far I am unable to achieve this.

// Resizes queue
int resize(queue *q) {

    // initialise new queue
    const int N = 2*q->n;
    queue p;
    init(&N, &p);

    // copy pairs from old to new queue
    for (int i = 0; i < q->m; i++) {
        pair f = dequeue(q);
        enqueue(&f, &p);
    }

    // destroy old queue
    destroy(q);

    // re-assign pointer to new queue
    q = &p;

    return 0;
}
5
  • 1
    you didn't show enqueue but passing the address of a local variable is a big no-no if you store the address in your structure: you'll find out that all variables have the same address, and which is invalid when f goes out of scope Commented Oct 8, 2018 at 19:24
  • 1
    @Jean-FrançoisFabre I am pretty certain enqueue copies from provided pointer - this is how it is usually done. Commented Oct 8, 2018 at 19:26
  • 1
    Passing a pointer to a const integer is an exercise in code obfuscation. I urge you to favor pass by vale for n. Commented Oct 8, 2018 at 20:31
  • @StoryTeller, could you please elaborate on this? Why is this an exercise in code obfuscation? Commented Oct 9, 2018 at 10:21
  • 1
    Passing a pointer to an object is usually done to one for one prominent reason: to allow modifications on an object out of the function's scope. But you just want the value of the integer at the point of the function call. That's what pass by value is for. It's clear and easy to reason about. Fogging it up with a pointer does not make for a good program to reason about. Commented Oct 9, 2018 at 10:26

1 Answer 1

2

Reassigning the pointer is completely useless. You changed it locally, but that didn't modify the original object. What you did was destroying the original queue, with nothing left in place.

What you want to do is to modify provided object in-place.

For example:

*q = p; 
Sign up to request clarification or add additional context in comments.

2 Comments

Do I understand correctly, that the queue destruction in this case is no longer necessary?
@mabalenk You still want to destruct the queue, so that the old array would be freed.

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.