paldepind
paldepind

Reputation: 4870

How to get size of different kinds of types in the same function using C?

I'm writing a function which increases the size of a dynamic memory object created with malloc. The function should as arguments take a pointer to the memory block to be increased, the current size of the block and the amount the block is going to be increased.

Something like this:

int getMoreSpace(void **pnt, int size, int add) {
    xxxxxx *tmp; /* a pointer to the same as pnt */
    if (tmp = realloc(pnt, (size+add)*sizeof(xxxxxx))) { /* get size of what pnt points to */
        *pnt=tmp;
        return 1;
    else return 0;
}

The problem is that I want the function to work no matter what pnt points to. How do I achieve that?

Upvotes: 1

Views: 240

Answers (3)

John Bode
John Bode

Reputation: 123458

Pass in the element size as a separate parameter:

int getMoreSpace(void **pnt, int size, int add, size_t eltSize) 
{     
  void *tmp;
  if (tmp = realloc(pnt, (size+add)*eltSize)) 
  { 
    *pnt=tmp;
    return 1;
  }
  else 
    return 0; 
} 
...

int *p = malloc(100 * sizeof *p);
...
if (!getMoreSpace(&p, 100, 20, sizeof *p))
{
  // panic
}

It's the most straightforward solution, if not the most elegant. C just doesn't lend itself to dynamic type information.

Edit

Changed the type of pnt in response to Steve's comment.

As caf points out, this won't work, even with the "fix" per Steve. R.'s right; don't do this.

Upvotes: 1

Ben Jackson
Ben Jackson

Reputation: 93720

You pass in the size as an argument. You can use a convenience macro to make it look the same as your function:

#define getMoreSpace(P, SZ, ADD) getMoreSpaceFunc(&(P), sizeof(*(P)), (SZ), (ADD))

int getMoreSpace(void **pnt, size_t elem_size, int size, int add) {
    *pnt = ...
}

Edit to show that your convenience macro would also need to add call-by-reference semantics.

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215261

This type of function cannot possibly work, because pnt is local and the new pointer is lost as soon as the function returns. You could take an argument of type xxxxxx ** so that you could update the pointer, but then you're stuck with only supporting a single type.

The real problem is that you're writing an unnecessary and harmful wrapper for realloc. Simply use realloc directly as it was meant to be used. There is no way to make it simpler or more efficient by wrapping it; it's already as simple as possible.

Upvotes: 9

Related Questions