[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Does this confirm to ISO C?

?????? ?????

9/11/2011 7:49:00 PM

I want to hide several fields within structure from "client" code. Can
I use following (just example):

- declare struct X { int visible; }; in "export.h" and several
functions, which take struct X as an argument;
- "export.h" is included by client code;
- declare struct X { int visible; int hidden; }; in "private.h";
- "private.h" is included in .c file which contains definitions of
functions which work with struct X

Thus, when mentioned functions process struct X, they may access to
hidden integer, however external code even doesn't suspect that there
is one.

The first issue of this technique is that client code cannot hold
allocation.
8 Answers

Eric Sosman

9/11/2011 9:19:00 PM

0

On 9/11/2011 3:49 PM, Ð?аксим Фомин wrote:
> I want to hide several fields within structure from "client" code. Can
> I use following (just example):
>
> - declare struct X { int visible; }; in "export.h" and several
> functions, which take struct X as an argument;
> - "export.h" is included by client code;
> - declare struct X { int visible; int hidden; }; in "private.h";
> - "private.h" is included in .c file which contains definitions of
> functions which work with struct X
>
> Thus, when mentioned functions process struct X, they may access to
> hidden integer, however external code even doesn't suspect that there
> is one.

It's not guaranteed to work. True, the "visible" element will
appear at the same offset in both versions of "struct X," and if
"visible" actually encompasses several elements they will also appear
at the same offsets as long as both versions agree.[*] But the two
versions might have different alignment requirements -- not very
likely in what you've shown, but change hidden to a "double" and it
is entirely plausible that the complete "struct X" could require
stricter alignment than the abbreviated version.

[*] Actually, the Standard only *guarantees* this if the two
versions both appear in the same union. But nobody's ever seen an
actual compiler where it wouldn't hold, even without the union.

Besides, there's a better way (which also avoids the confusion
of having two different versions of "struct X" floating around).
Use two different structs, one public and one private, and embed
the public version inside the private:

struct public {
int visible;
...
};

struct private {
struct public export;
int hidden;
FILE *stream;
char *stuff;
...
};

Your library code should deal in "struct public *" pointers, which
you know always point to the "export" element of a "struct private"
instance. So internally

void foo(struct public *bar) {
struct private *baz = (struct private*)bar;
baz->hidden = 42;
}

> The first issue of this technique is that client code cannot hold
> allocation.

The usual way to deal with this is to have the library manage
the storage, and let the client deal only with pointers to it:

struct public *factory(void) {
struct private *baz = malloc(sizeof *baz);
baz->stream = fopen("file.dat", "r");
baz->stuff = malloc(42);
...
return &baz->export;
}

void oubliette(struct public *junk) {
struct private *baz = (struct private*)junk;
fclose(baz->stream);
free(baz->stuff);
...
free(baz); // or free(junk) in simple cases
}

--
Eric Sosman
esosman@ieee-dot-org.invalid

jt

9/11/2011 9:22:00 PM

0

Ð?аксим Фомин <maxim@maxim-fomin.ru> wrote:
> I want to hide several fields within structure from "client" code. Can
> I use following (just example):

> - declare struct X { int visible; }; in "export.h" and several
> functions, which take struct X as an argument;
> - "export.h" is included by client code;
> - declare struct X { int visible; int hidden; }; in "private.h";
> - "private.h" is included in .c file which contains definitions of
> functions which work with struct X

> Thus, when mentioned functions process struct X, they may access to
> hidden integer, however external code even doesn't suspect that there
> is one.

> The first issue of this technique is that client code cannot hold
> allocation.

Looks extremely dirty to me, especially naming both the same.
And yes, the user can't allocate such a structure, nor can he
make copies - and there's nothing that would allow you to
control that the client doesn't do it anyway and mess up your
whole scheme. And you can only pass pointers to the struc-
ture between your and the clients code (otherwise the client
would need a full definition or things would get messed up
completely if the clients code would receive a larger struc-
ture than it is made to expect). Why not then simplify life
a lot by making it a completely opaque structure and export a
function that allows the client to set the visible member?
While you're at it you could also supply a function for allo-
cation and deallocation. Looks a lot safer to me and will cost
you not much more than the work of adding a rather small number
of functions. With a typedef you could even make it invisible
to the client that it's dealing with just pointers to that
kind of structures.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://t...

Ben Bacarisse

9/11/2011 9:58:00 PM

0

Ð?аксим Фомин <maxim@maxim-fomin.ru> writes:

> I want to hide several fields within structure from "client" code. Can
> I use following (just example):
>
> - declare struct X { int visible; }; in "export.h" and several
> functions, which take struct X as an argument;
> - "export.h" is included by client code;
> - declare struct X { int visible; int hidden; }; in "private.h";
> - "private.h" is included in .c file which contains definitions of
> functions which work with struct X

Just to clarify: you mean pointers to these structs will be passed, yes?
You don't say so but without passing pointers it is certain to fail so
it seems like a reasonable assumption.

> Thus, when mentioned functions process struct X, they may access to
> hidden integer, however external code even doesn't suspect that there
> is one.
>
> The first issue of this technique is that client code cannot hold
> allocation.

If the allocation is "behind the wall" so to speak, have you considered:

struct X { int visible; };

struct Y { struct X x; int hidden; };

The allocator makes a struct Y but passes &Y.x to the client. When the
client passes &Y.x back to the other side of the wall, the conversion
from struct X * back to struct Y * is certain to work.

--
Ben.

Fred

9/12/2011 2:53:00 PM

0

On Sep 11, 2:58 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> ?????? ????? <ma....@maxim-fomin.ru> writes:
> > I want to hide several fields within structure from "client" code. Can
> > I use following (just example):
>
> > - declare struct X { int visible; }; in "export.h" and several
> > functions, which take struct X as an argument;
> > - "export.h" is included by client code;
> > - declare struct X { int visible; int hidden; }; in "private.h";
> > - "private.h" is included in .c file which contains definitions of
> > functions which work with struct X
>
> Just to clarify: you mean pointers to these structs will be passed, yes?
> You don't say so but without passing pointers it is certain to fail so
> it seems like a reasonable assumption.
>
> > Thus, when mentioned functions process struct X, they may access to
> > hidden integer, however external code even doesn't suspect that there
> > is one.
>
> > The first issue of this technique is that client code cannot hold
> > allocation.
>
> If the allocation is "behind the wall" so to speak, have you considered:
>
>   struct X { int visible; };
>
>   struct Y { struct X x; int hidden; };
>
> The allocator makes a struct Y but passes &Y.x to the client.  When the
> client passes &Y.x back to the other side of the wall, the conversion
> from struct X * back to struct Y * is certain to work.
>
> --
> Ben.

And what happens if one declares an array of X's, then tries to
access
x[1].visible ?

--
Fred K

Ben Bacarisse

9/12/2011 7:02:00 PM

0

Fred <fred.l.kleinschmidt@boeing.com> writes:

> On Sep 11, 2:58 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> Ð?аксим Фомин <ma...@maxim-fomin.ru> writes:
>> > I want to hide several fields within structure from "client" code. Can
>> > I use following (just example):
>>
>> > - declare struct X { int visible; }; in "export.h" and several
>> > functions, which take struct X as an argument;
>> > - "export.h" is included by client code;
>> > - declare struct X { int visible; int hidden; }; in "private.h";
>> > - "private.h" is included in .c file which contains definitions of
>> > functions which work with struct X
>>
>> Just to clarify: you mean pointers to these structs will be passed, yes?
>> You don't say so but without passing pointers it is certain to fail so
>> it seems like a reasonable assumption.
>>
>> > Thus, when mentioned functions process struct X, they may access to
>> > hidden integer, however external code even doesn't suspect that there
>> > is one.
>>
>> > The first issue of this technique is that client code cannot hold
>> > allocation.
>>
>> If the allocation is "behind the wall" so to speak, have you considered:
>>
>>   struct X { int visible; };
>>
>>   struct Y { struct X x; int hidden; };
>>
>> The allocator makes a struct Y but passes &Y.x to the client.  When the
>> client passes &Y.x back to the other side of the wall, the conversion
>> from struct X * back to struct Y * is certain to work.
>>
>> --
>> Ben.

It's better to snip sigs.

> And what happens if one declares an array of X's, then tries to
> access
> x[1].visible ?

Exactly what you'd expect happens. I know that was a rhetorical
question but I'm not sure what else to say. Yes, arrays don't work with
this scheme, but they won't work with any scheme where the size of the
actual allocation is hidden from the "client" side. Presumably the OP
accepts that restriction and would use and array of pointers instead.

--
Ben.

Eric Sosman

9/13/2011 12:17:00 AM

0

On 9/12/2011 3:01 PM, Ben Bacarisse wrote:
> Fred<fred.l.kleinschmidt@boeing.com> writes:
>
>> On Sep 11, 2:58 pm, Ben Bacarisse<ben.use...@bsb.me.uk> wrote:
>>> Ð?аксим Фомин<ma...@maxim-fomin.ru> writes:
>>>> I want to hide several fields within structure from "client" code. Can
>>>> I use following (just example):
>>>
>>>> - declare struct X { int visible; }; in "export.h" and several
>>>> functions, which take struct X as an argument;
>>>> - "export.h" is included by client code;
>>>> - declare struct X { int visible; int hidden; }; in "private.h";
>>>> - "private.h" is included in .c file which contains definitions of
>>>> functions which work with struct X
>>>
>>> Just to clarify: you mean pointers to these structs will be passed, yes?
>>> You don't say so but without passing pointers it is certain to fail so
>>> it seems like a reasonable assumption.
>>>
>>>> Thus, when mentioned functions process struct X, they may access to
>>>> hidden integer, however external code even doesn't suspect that there
>>>> is one.
>>>
>>>> The first issue of this technique is that client code cannot hold
>>>> allocation.
>>>
>>> If the allocation is "behind the wall" so to speak, have you considered:
>>>
>>> struct X { int visible; };
>>>
>>> struct Y { struct X x; int hidden; };
>>>
>>> The allocator makes a struct Y but passes&Y.x to the client. When the
>>> client passes&Y.x back to the other side of the wall, the conversion
>>> from struct X * back to struct Y * is certain to work.
>
>> And what happens if one declares an array of X's, then tries to
>> access
>> x[1].visible ?
>
> Exactly what you'd expect happens. I know that was a rhetorical
> question but I'm not sure what else to say. Yes, arrays don't work with
> this scheme, but they won't work with any scheme where the size of the
> actual allocation is hidden from the "client" side. Presumably the OP
> accepts that restriction and would use and array of pointers instead.

This is one reason the "visible" part is often entirely empty,
so the caller gets a pointer to a completely opaque object (formally,
an "incomplete type") and cannot possibly create a free-standing
instance on his own.

True, given a `struct X*' the caller cannot then access its
"visible" member(s). Instead of just peeking and poking at those
elements the caller must resort to accessor functions provided by
the library, "getters and setters" as our O-O friends might say.
That's a disadvantage, but usually not a crippling disadvantage.

--
Eric Sosman
esosman@ieee-dot-org.invalid

?????? ?????

9/13/2011 6:41:00 AM

0

Thank to everybody for clarification!

Phil Carmody

9/15/2011 11:40:00 AM

0

Eric Sosman <esosman@ieee-dot-org.invalid> writes:
> On 9/12/2011 3:01 PM, Ben Bacarisse wrote:
> This is one reason the "visible" part is often entirely empty,
> so the caller gets a pointer to a completely opaque object (formally,
> an "incomplete type") and cannot possibly create a free-standing
> instance on his own.

It's a minor nit, but I think I'd prefer to say that there
was no visible part in such a situation, rather than the
visible part being empty. The mathematician in me disagrees
with the rest of me, of course.

Phil
--
"Religion is what keeps the poor from murdering the rich."
-- Napoleon