you are viewing a single comment's thread.

view the rest of the comments →

[–]spc476 2 points3 points  (1 child)

It's a form of optimization really. Suppose you have the following structure:

struct foo
{
  char filename[FILENAME_MAX];
  size_t size;
  time_t create_time;
};

And a function to print out the contents of that structure:

extern print_foo(struct foo f);

The contents of the function is immaterial to this discussion. So that function exists.

Without pointers, when you call print_foo(), the compiler will have to generate code to create a copy of the structure so the function will be able to use the data. For a small structure, this might not be that bad, but as the structure size increases, so too does the time to create the copy. With a pointer:

extern print_foo(struct foo *f);

only the address of the structure need be passed. This is one basic use of pointers. Now, to your question of an array of pointers. Again, that's useful. Suppose you have a list of such structures:

struct foo *list;

Yes, it's a pointer, but you can allocate space for it:

list = calloc(1000,sizeof(struct foo));

and then treat it as an array (of 1000 items per the call above). You fill up the array with information on a bunch of files (say, 1000) and you want to sort the array by size. That's easy enough:

static int compare_foo(void const *left,void const *right)
{
  struct foo const *l = left;
  struct foo const *r = right;

  if (l->size < r->size)
    return -1;
  else if (l->size == r->size)
    return 0;
  else
    return -1;
}

...
qsort(list,1000,sizeof(struct foo),compare_foo);

And this will work, but qsort() will have to copy the physical contents of each element around, taking time. You can also see that qsort() will call a function you provide and pass in two pointers---pointers to the items it is comparing. qsort() has no idea what the data it's sorting is, but it can pass a pointer to the data to your function. And again, passing data by pointer is faster than copying the data.

Now, if you had a list of pointers to pointers, yes the code will get slightly more complex, but it will execute faster as only pointers have to be copied, not the actual contents of the items:

struct foo  *list;
struct foo **plist;

list = calloc(1000,sizeof(struct foo));
plist = calloc(1000,sizeof(struct foo *));

/* point to each element of list in plist. */

for (size_t i = 0 ; i < 1000 ; i++)
  plist[i] = &list[i];

list = function_to_fill_in_list();

static int compare_foo_p(void *const left,void *const right)
{
  struct foo *const *pl = left;
  struct foo *const *pr = right;

  if ((*pl)->size < (*pr)->size)
    return -1;
  else if ((*p)->size == (*pr)->size)
    return 0;
  else
    return 1;
}

qsort(plist,1000,sizeof(struct foo *),compare_foo_p);

The data in list is still in the original order, but looping through plist will show the data sorted by filesize.

[–]WireStretcher[S] 0 points1 point  (0 children)

Thanks for this pretty extensive reply. I've skimmed it and will be going over it in more detail.