Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Public/private in C

3 views
Skip to first unread message

jacob navia

unread,
Mar 21, 2010, 6:20:09 PM3/21/10
to
As you may have noticed, when I proposed the iterator object I splitted
the object into a public part (the first 3 fields) an an undisclosed
part specific to each iterator.

This inheritance implementation looks like this:

In the header file:

typedef struct PublicStruct {
// public fields
} Public;

In the implementation file (.c) we do:

typedef struct Inherited {
Public p;
// follow the private fields
} Private;

The interface for all functions is just the public structure:

void fn1(Public *);
void fn2(Public *);

The implementation of fn1 however, does this:

void fn1(Public *p) {
Private *pri = (Private *)p;

// Work with the private struct.
// It is assumed that the pointer
// handed down is actually a private
// pointer

}

Obviously this doesn't have any compiler support
but works quite well in practice. You can add a
"magic" number somewhere in the private struct
in the debug version to catch mistakes when passing
the structures.

Obviously you aren't supposed to copy the public object since you do not
know what is behind. A way to avoid that would be to add a VLA:

typedef struct PublicStruct {
// public fields
// ...
// private fields follow:
char private[];
} Public;


YES I KNOW.

C++/Java/C# do this MUCH better, but they have other drawbacks
that make a pure C solution MUCH better. Thank you.

Ian Collins

unread,
Mar 21, 2010, 6:34:08 PM3/21/10
to
On 03/22/10 11:20 AM, jacob navia wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.

<snip example>

> Obviously this doesn't have any compiler support
> but works quite well in practice. You can add a
> "magic" number somewhere in the private struct
> in the debug version to catch mistakes when passing
> the structures.
>
> Obviously you aren't supposed to copy the public object since you do not
> know what is behind. A way to avoid that would be to add a VLA:
>
> typedef struct PublicStruct {
> // public fields
> // ...
> // private fields follow:
> char private[];

This isn't a VLA, its an example of the "struct hack".

> } Public;

You can still copy these. It's not a good idea, but there's nothing to
prevent the copy.

> YES I KNOW.
>
> C++/Java/C# do this MUCH better, but they have other drawbacks
> that make a pure C solution MUCH better. Thank you.

In this instance, please elaborate!

--
Ian Collins

Keith Thompson

unread,
Mar 21, 2010, 6:43:35 PM3/21/10
to
Ian Collins <ian-...@hotmail.com> writes:
> On 03/22/10 11:20 AM, jacob navia wrote:
[...]

>> typedef struct PublicStruct {
>> // public fields
>> // ...
>> // private fields follow:
>> char private[];
>
> This isn't a VLA, its an example of the "struct hack".
>
>> } Public;
[...]

More precisely, it's a "flexible array member", C99's replacement for
the "struct hack".

Incidentally, jacob's declaration for the struct was properly
indented, but the indentation vanished in Ian's followup, probably
because of the use of tabs. At least for Usenet posts, spaces are
better than tabs for indentation, since news software doesn't always
deal sanely with tabs.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Hamiral

unread,
Mar 21, 2010, 6:57:53 PM3/21/10
to
jacob navia wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.

Interesting.
Do you have something similar for inheritance, or... polymorphism ? That
would be great :)

Ham

ImpalerCore

unread,
Mar 22, 2010, 11:28:23 AM3/22/10
to

Personally I think implementing some public/private separation is
outside the scope of C. Grafting this OO paradigm into C is purely
arbitrary at best, confusing and complex at worst. C wants people to
get their hands dirty, and doesn't do a whole lot to protect them.

Again, you say a pure C solution is MUCH better, but I haven't seen a
really cool use-case that says "Yeah, I want to try it out!". If I
wanted to make something private in C, I'd just give the "private"
members a hideously long name so that most people will just be annoyed/
bored to type it out and use the "public" parts ;)

Best regards,
John D.

jacob navia

unread,
Mar 22, 2010, 2:57:43 PM3/22/10
to
ImpalerCore a écrit :

> Personally I think implementing some public/private separation is
> outside the scope of C. Grafting this OO paradigm into C is purely
> arbitrary at best, confusing and complex at worst. C wants people to
> get their hands dirty, and doesn't do a whole lot to protect them.
>

Well, as you may have noticed, I proposed a common iterator object for
iterating through ANY container in my library. Obviously that object
can't be a SINGLE type, it must be several since it must have the specific
knowledge of each container, AND it must offer a COMMON interface, so user
code is independent of the container.

It is not just "a matter of protecting people from themselves", it is
just that is impossible to make a COMMON type for all container iterators
if each iterator exposes its interface.

The solution is then, to define a common interface with a few
function pointers that is shared by all containers. User code uses that
interface

typedef struct _iterator {
void (*Getnext)(structb_iterator *);
// Some other public function pointers
char private[]; // Document that this is a variable length structure
} Iterator;

In the file of the container implementation (say list.c) I
define

typedef struct tagListIterator {
Iterator it;
// Private fields follow
List *list;
unsigned timestamp;
// etc
} ListIterator;

Now, I can define

static void *GetNext(Iterator *it)
{
ListIterator *li = (ListIterator *)it;

// And now I can use the private fields
// in this implementation.
}

The advantage of this is that I can EXTEND a public structure with private
parts, something similar to simple inheritance in C.

> Again, you say a pure C solution is MUCH better, but I haven't seen a
> really cool use-case that says "Yeah, I want to try it out!".

When you write a library, it is very handy since it allows to present a common
interface for a set of different objects

> If I
> wanted to make something private in C, I'd just give the "private"
> members a hideously long name so that most people will just be annoyed/
> bored to type it out and use the "public" parts ;)
>
> Best regards,
> John D.

It is not so much a "private" vs public stuff but it is a thing of
interfacing different objects of different types through a common interface.

Branimir Maksimovic

unread,
Mar 22, 2010, 3:06:42 PM3/22/10
to
On Mon, 22 Mar 2010 19:57:43 +0100
jacob navia <ja...@nospam.org> wrote:

> ImpalerCore a écrit :
>
> > Personally I think implementing some public/private separation is
> > outside the scope of C. Grafting this OO paradigm into C is purely
> > arbitrary at best, confusing and complex at worst. C wants people
> > to get their hands dirty, and doesn't do a whole lot to protect
> > them.
> >
>
> Well, as you may have noticed, I proposed a common iterator object for
> iterating through ANY container in my library. Obviously that object
> can't be a SINGLE type, it must be several since it must have the
> specific knowledge of each container, AND it must offer a COMMON
> interface, so user code is independent of the container.

Well, that's not good. Better implement it through macros as
in c++. Heterogeneous iterators and containers are not
that useful. Os just make macro with specified type for
only one type of container which holds certain type,
and you are set up.
Most powerful feature of C++ are templates (type checked macros).
Just IMO. I looked at java containers and found them not
efficient and useful as C++ one macro based, not inheritance
based. Good thing with C++ iterator is that it mimics pointers,
so generic algorithm can work both on eg vector and plain array.
I suggest that you examine C++ CTL and think in that direction
eg macros.

Greets!

Greets!

--
http://maxa.homedns.org/

Sometimes online sometimes not


balson

unread,
Mar 23, 2010, 9:02:59 AM3/23/10
to
jacob navia wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.
>

[snip...]

>
> C++/Java/C# do this MUCH better, but they have other drawbacks
> that make a pure C solution MUCH better. Thank you.


Yes Java and C# do this, but they are way to slow. I like oyur
implementation here though.


Jim


ImpalerCore

unread,
Mar 23, 2010, 10:40:38 AM3/23/10
to

I can see your viewpoint better now, between this and your other
responses.

> > Again, you say a pure C solution is MUCH better, but I haven't seen a
> > really cool use-case that says "Yeah, I want to try it out!".
>
> When you write a library, it is very handy since it allows to present a common
> interface for a set of different objects

Fair enough, I'll wait to see how it all works when you release
something.

> > If I
> > wanted to make something private in C, I'd just give the "private"
> > members a hideously long name so that most people will just be annoyed/
> > bored to type it out and use the "public" parts ;)
>
> > Best regards,
> > John D.
>
> It is not so much a "private" vs public stuff but it is a thing of
> interfacing different objects of different types through a common interface.

I suppose I took the private/public too literally. Probably a by-
product of learning C++ then coming to C I suppose.

Best regards,
John D.

Anand Hariharan

unread,
Mar 23, 2010, 10:53:56 AM3/23/10
to


Am not sure if there is a question here. Also, you may already know
this, but you can control/restrict access by using the 'pimpl' idiom
(also known as the 'opaque structure'). Herb Sutter has written an
article or two regarding this (yes, they are C++ based, but the ideas
can be applied to C).

Basically you forward declare a structure that you want to be private
like so:

struct MyStructPrivates; /* forward declaration */

struct MyStruct
{
/* All your "public" stuff here */

struct MyStructPrivates *PtrToPrivate;
};

In the declaration of MyStructPrivates, you include the declaration of
MyStruct so you have access to the public parts of your struct.

The declaration of MyStructPrivates does not even have to be delivered
to the library user. Further, if anything changes in the
implementation of MyStructPrivates, your library users will remain
unaffected.

I haven't followed the other thread or read your iterator design, it
is possible I am way off-tangent here.

- Anand

Lorenzo Villari

unread,
Mar 23, 2010, 12:20:23 PM3/23/10
to

It looks a bit like what they did in the Athena Widget Set for X11. In
that case there was an interesting concept obscured by typedefs
and other things. This seems less obscure at first sight. Good
luck and good work :)


0 new messages