Let me start by explaining what (a sample of) this "C" code
means:
Code:
struct ipa__data_s {
ipa__serv_t service;
long bytes;
long packets;
};
typedef struct ipa__data_s ipa__data_t;
We see that:
- A memory structure called ipa__data_s consists of three elements: (1) a pointer to a thing of type ipa__data_t, which is described previously; (2) a long-intger named bytes; and (3) another long-integer named packets.
- When we declare a variable to be "of type ipa__data_t," we mean that it is an instance of the struct(ure) ipa__data_s.
- None of these structures contains "a pointer to another instance of itself." Instead, we see a single pointer of the appropriate type, and a long-integer with a name like __size. So, what the designer intends for us to do is to malloc() a single contiguous block of memory that is big enough to contain ("an array of") n instances of this thing, and to remember the number of elements ("n") in __size.
- This is an experienced designer, who has adopted the nomenclature that structure-names end with _s (for "structure") and each structure is then declared as a typedef ending in _t (for "type"). This designer also observes the convention that, when variable-names begin with one or two underscores, as in __size, she wishes to thereby convey that this element is intended "for internal use only," i.e. for managing this thing, not as a piece of information someone else might wish to know. ("C" does not have objects, with formal visibility rules, methods, constructors and destructors, and so on.)
If you review
man malloc, you will see definitions of functions with parameter-lists like these:
Code:
void *calloc(size_t nmemb, size_t size);
This is designed to allocate a block of memory consisting of
nmemb instances of a structure of size
size. In the "C" language, this allocates "an array."
I strongly recommend that you check to see if this unit does not already define some routines which are intended to build and dismantle these structures: if not, you should build them yourself and use them throughout. Write one or more "C" units which encapsulate the entire process of correctly building, dismantling,
and using these structures, so that the remainder of your code can treat them "opaquely," that is, without concerning itself with structural details: "I want to remember this, so I call this routine to do that. I want to know this answer, so I call this routine to get it. In both cases, I don't care how it works." Thus, if a bug appears, there is
one and only one place to look for it.
It might be most useful for you to do some browsing through, say, some of the include-files in
/usr/include to see first-hand some examples of the techniques I am talking about.