Re: Pointers, structs and memory allocations

From: Zoran Cutura (zoran.cutura_at_daimlerchrysler.com)
Date: 11/11/03


Date: 11 Nov 2003 16:35:33 GMT

Christian F <khola@telia.com> wrote:
> Hi, I'm a C-newbie and I would like to know if I am doing something
> wrong in the code below. It is working, but I'm afraid it might not be
> correct because I don't really understand everything of it. There are
> lots of pointers and pointers to pointers which makes me confused.
>
> First my typedef:
>
> typedef struct
> {
> double re;
> double im;
> } cplx;

Though the above is syntactically correct, IMHO it brings you no good.
Hiding structs behind typedefs is only a good idea if the struct needs
to be camouflaged somehow. That is, programs use an abstract type they
do not have to know in depth (like for example the type FILE).

It is arguable that a complex-type should be abstracted to the user, but
on the other hand it should not for the part of the program that works
with the contents of such a struct.

I usually stick to the conservative

struct cplx {...};

.

>
> What I need to do first is to allocate memory to hold N pointers to
> cplx. I do it with this statement (correct or not?):
>
> cplx **data = (cplx **)malloc(sizeof(cplx *) * N);

Casting malloc is a no no, especially in this newsgroup. If you have the
appropriate prototype for malloc in place, there is no need to cast its
return value at all. malloc returns a generic pointer, which can be
converted without a cast to any other object pointer type. So if you are
getting diagnostic messages from you compiler, that is rather due to
failure to include tha correct header file (stdlib.h), that to a missing
cast.

Some people argue that in C++ you'ld need cast mallocs return value, but
who would ever want to compile a C program with a C++ compiler? And if
one is programming in C++, why would one use malloc at all? ...

Also I recommend to apply sizeof to an object rather than a type, so
when you change the type of data, there will be no need to change the
malloc call:

  struct cplx **data = malloc(sizeof *data * N);

Btw, if N is meant to be constant, I don't see the need to use malloc
at all, but I think this is going to be a parameter of some kind.

> if(!data) { /* malloc failed */ ... }
>
> Next I need to malloc space for each struct in the list and fill it
> with data. This is what I do (correct or not?):
>
> for(i = 0; i < N; i++)
> {
> data[i] = (cplx *)malloc(sizeof(cplx));

As explained above:
  data[i] = malloc(sizeof *data[i]);

> data[i]->re = i; /* fill with testdata */
> data[i]->im = N - i - 1; /* fill with testdata */
> }
>
> Then I will call a rearrange-function to rearrange the _pointers_ and
> _not_ the data in the array. The function looks like this:
>
> void rearrange(cplx **data, int n_elements)
> {
> cplx *tmp;
> int i;
>
> /* reverse the data */
> for(i = 0; i < (n_elements / 2); i++)
> {
> tmp = data[i];
> data[i] = data[n_elements - i - 1];
> data[n_elements - i - 1] = tmp;
> }
> }
>
> I call this function from main() the following way (correct or not?):
>
> rearrange(data, N);
>
> And finally clean up the memory (correct or not?):
>
> for(i = 0; i < N; i++)
> free(data[i]);

That is ok!

>
> free(**data);

But this one is not. Guess why!

 free(data);
 
>
> Finally, is this the right approach if you got a large list of structs
> to be rearranged? I guess it's much faster swapping pointers than
> swapping the entire data in the structs?

It depends one the size of the list. It is probably the right approach
for lists that are pretty short (like less than say 1000 elements). At
some point you may recognize that there need to be better ways of doing,
but that is another story... which is better discussed elsewhere.

-- 
Z (Zoran.Cutura@daimlerchrysler.com)
"LISP  is worth learning for  the profound enlightenment  experience
you will have when you finally get it; that experience will make you
a better programmer for the rest of your days."   -- Eric S. Raymond 


Relevant Pages

  • Re: alignment question about pointer conversion
    ... Is this going to be an array of pointers to nodes or just a memory ... linked lists are implemented using pointers to the ... struct s1; ...
    (comp.lang.c)
  • Re: alignment question about pointer conversion
    ... Is this going to be an array of pointers to nodes or just a memory ... linked lists are implemented using pointers to the ... for example, if a struct as ...
    (comp.lang.c)
  • Re: Data importing BUS ERROR
    ... You declare an array of 1000 pointers to struct. ... Then you malloc memory for 1 struct, ...
    (comp.lang.c)
  • Re: Required DataType ???
    ... I also have a class B, that stores lists of type X's and type ... > pointers to elements of L? ... > struct X; ... Well MRF don't operate on the sites alone, they operate on cliques ...
    (comp.lang.cpp)
  • Re: Offset/alignement of structure members
    ... Have the lists manipulated by code that ... preserves those generic pointers, which have to be of type void*. ... struct node *next; ...
    (comp.lang.c)