1
votes

I hope you can help me! I added this function to my array.c to shuffle the array elements and it works with static Item *a; static int dim; in my array.c.

static Item *a; 
static int dim = 3;

a=malloc( dim * sizeof(Item);

void random_array() {
                                  int i , j;
                                  Item t;
                                  for (i = dim - 1;i > 0; i--)
                                  {
                                      j = rand() % (i + 1);
                                      t = a[i];
                                      a[i] = a[j];
                                      a[j] = t;
                                     //swap(a[i], a[j]);
                                  }
                           }

item.h

typedef void *Item;

item-int.c

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

Item inputItem(){
    int *p;
    p=malloc(sizeof(int));
    scanf("%d",p);
    return p;
}

void outputItem(Item item){
    int *p;
    p=item;
    printf("%d ",*p);
}

int cmpItem(Item item1,Item item2){
    int *p1,*p2;
    p1 = item1;
    p2 = item2;
    return *p1 - *p2;

}

So I tried with a function swap (a[i], a[j]) from the file utils.c but it doesn't work.

void swap (Item pa, Item pb) {
    Item t;
    t = pa;
    pa = pb;
    pb = t;
}

It works with these instructions:

void swap (Item *pa, Item *pb) 
{
    Item t;
    t = *pa;
    *pa = *pb;
    *pb = t;
}

I know that with "typedef void *Item' Item t is like void *t and Item *a is like void **a, right? So with double pointers I have a dynamic array with many pointers thanks to a=malloc(numberelements*(sizeof(Item)); and with a[i]=malloc(sizeof(Item) every pointer points to a memory location with many bytes?

Here a image.

So for t I don't need malloc because with t = a[i] t points to memory location pointed from a[i], right? If yes, why do I have to use in my swap function t = *pa etc. instead of t = pa ? I have several doubts about double pointers as function parameters. I hope you can resolve that. Thanks in advance!

1
This is the difference between pass by value and pass by reference. Your first example makes copies of everything then throws away the work at the end of the function. The second works with the original pointers to items and stores the values back. It is correct - you will need to pass the address of your elements to it for it to work though using &. And yes, this will work with pointers if that is what Item really is.Michael Dorgan
Write a simple void swap(int *pa, int *pb) function first, and make sure you understand what it does and how to use it. Trying to do it with void * from the start only obfuscates the simpler things.dxiv
Thanks for your answers! So with swap(a[i], a[j]) I give they addresses to Item *pa (void **pa) and Item *pb (void *pb) for reference? For me is easy pass by reference with normal variable (using &) and single pointer. But here I have pointer a[i] and double pointer. Is my thought drawn on the image correct? It's to see if I understood the double pointer void (Item *a) correctly in this exercise. @MichaelDorganTsuhirito
Forget what type you are swapping. It could be a *****int. All a pointer is is a number that represents some address and you can swap those too without a worry. As far as the swap is concerned, it's moving a number the size of the type around - pointer size for pointer, integer for integer, Item for Item. Now, if you understand the difference between pass by value and pass by reference, the rest should be clear. Pass the reference (the address &) and use that reference to modify the original value (the *pa. *pb parts).Michael Dorgan
So with pointers I don't need & for pass the address of these pointers? Because with swap I have swap(a[i], a[j]) and not swap(&a[i], &a[j]) @MichaelDorganTsuhirito

1 Answers

0
votes

Ok, let's start from here:

typedef int Item;  // Always get this backwards, need to check...

void swap (Item *pa, Item *pb) 
{
    Item t;
    t = *pa;
    *pa = *pb;
    *pb = t;
}

void foo()
{
    Item i= (Item), j=(Item)2;  // These casts are not needed, but help later explanations

    // Must take address so swap can change original values of i and j.
    swap(&i, &j);

    Item *ip = &i;
    Item *jp = &j;

    // This also works because we do the dereference above.
    swap(ip, jj);
}

Either are fine. What about?

typedef int******* Item;

void swap (Item *pa, Item *pb) 
{
    Item t;
    t = *pa;
    *pa = *pb;
    *pb = t;
}

void foo()
{
    Item i= (Item)1, j=(Item)2;

    // Must take address so swap can change original values of i and j.
    swap(&i, &j);

    int *ip = &i;
    int *jp = &j;

    // This also works because we do the dereference above.
    swap(ip, jp);
}

Again, the type doesn't matter. It's how it's used. If you were to forget the &, the compiler would warn you about type mismatch.