Opaque pointers

Discussion in 'C Programming' started by chankl, Aug 17, 2006.

  1. chankl

    chankl Guest

    Can anyone explain what's an opaque pointer and how it's implemented in
    C?

    I read about this concept in the book "C interfaces and
    implementations".

    Here's an example from the book (list.h - available from the website):

    #define T List_T

    typedef struct T *T;
    struct T {
    T rest;
    void *first;
    };

    extern T List_append (T list, T tail);
    extern T List_copy (T list);
    extern T List_list (void *x, ...);
    ..
    ..
    and so on...

    It seems the struct behind List_T is now hidden from the application
    using these functions.The contents of List_T cannot be accessed (or
    dereferenced?).

    But I don't see why not. If I have access to the header file, wouldn't
    I be able to dereference the contents of the structure? Or am I missing
    the meaning of opaque?

    Any answers is much appreciated.
     
    chankl, Aug 17, 2006
    #1
    1. Advertising

  2. chankl wrote:
    > Can anyone explain what's an opaque pointer and how it's implemented in
    > C?
    >
    > I read about this concept in the book "C interfaces and
    > implementations".
    >
    > Here's an example from the book (list.h - available from the website):
    >
    > #define T List_T
    >
    > typedef struct T *T;
    > struct T {
    > T rest;
    > void *first;
    > };
    >
    > extern T List_append (T list, T tail);
    > extern T List_copy (T list);
    > extern T List_list (void *x, ...);
    > .
    > .
    > and so on...
    >
    > It seems the struct behind List_T is now hidden from the application
    > using these functions.The contents of List_T cannot be accessed (or
    > dereferenced?).
    >
    > But I don't see why not. If I have access to the header file, wouldn't
    > I be able to dereference the contents of the structure? Or am I missing
    > the meaning of opaque?
    >
    > Any answers is much appreciated.
    >


    In your header file, you'd have something along the lines of:

    foo.h
    -----
    typedef struct foo foo;

    foo *create_foo(void);
    void destroy_foo(foo *ptr);

    void use_foo(foo *ptr);

    The actual definition of 'struct foo' goes in the source file:

    foo.c
    -----
    struct foo
    {
    /* ... */
    };

    So that it's only foo.c that knows what the contents of a struct foo
    are. The contents are hidden, ie opaque, from everything that merely
    includes foo.h - all you can do is pass pointers around.

    --
    rh
     
    Richard Harnden, Aug 17, 2006
    #2
    1. Advertising

  3. chankl

    pete Guest

    Richard Harnden wrote:
    >
    > chankl wrote:
    > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > C?
    > >
    > > I read about this concept in the book "C interfaces and
    > > implementations".
    > >
    > > Here's an example from the book (list.h - available from the website):
    > >
    > > #define T List_T
    > >
    > > typedef struct T *T;
    > > struct T {
    > > T rest;
    > > void *first;
    > > };
    > >
    > > extern T List_append (T list, T tail);
    > > extern T List_copy (T list);
    > > extern T List_list (void *x, ...);
    > > .
    > > .
    > > and so on...
    > >
    > > It seems the struct behind List_T is now hidden from the application
    > > using these functions.The contents of List_T cannot be accessed (or
    > > dereferenced?).
    > >
    > > But I don't see why not. If I have access to the header file, wouldn't
    > > I be able to dereference the contents of the structure? Or am I missing
    > > the meaning of opaque?
    > >
    > > Any answers is much appreciated.
    > >

    >
    > In your header file, you'd have something along the lines of:
    >
    > foo.h
    > -----
    > typedef struct foo foo;
    >
    > foo *create_foo(void);
    > void destroy_foo(foo *ptr);
    >
    > void use_foo(foo *ptr);
    >
    > The actual definition of 'struct foo' goes in the source file:
    >
    > foo.c
    > -----
    > struct foo
    > {
    > /* ... */
    > };
    >
    > So that it's only foo.c that knows what the contents of a struct foo
    > are. The contents are hidden, ie opaque, from everything that merely
    > includes foo.h - all you can do is pass pointers around.


    That's wrong.
    The defintion of the stuct type needs to be in the header file.
    Otherwise,
    void destroy_foo(foo *ptr);
    wouldn't mean anything in the header file.

    --
    pete
     
    pete, Aug 17, 2006
    #3
  4. chankl

    pete Guest

    pete wrote:
    >
    > Richard Harnden wrote:
    > >
    > > chankl wrote:
    > > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > > C?
    > > >
    > > > I read about this concept in the book "C interfaces and
    > > > implementations".
    > > >
    > > > Here's an example from the book (list.h - available from the website):
    > > >
    > > > #define T List_T
    > > >
    > > > typedef struct T *T;
    > > > struct T {
    > > > T rest;
    > > > void *first;
    > > > };
    > > >
    > > > extern T List_append (T list, T tail);
    > > > extern T List_copy (T list);
    > > > extern T List_list (void *x, ...);
    > > > .
    > > > .
    > > > and so on...
    > > >
    > > > It seems the struct behind List_T is now hidden from the application
    > > > using these functions.The contents of List_T cannot be accessed (or
    > > > dereferenced?).
    > > >
    > > > But I don't see why not. If I have access to the header file, wouldn't
    > > > I be able to dereference the contents of the structure? Or am I missing
    > > > the meaning of opaque?
    > > >
    > > > Any answers is much appreciated.
    > > >

    > >
    > > In your header file, you'd have something along the lines of:
    > >
    > > foo.h
    > > -----
    > > typedef struct foo foo;
    > >
    > > foo *create_foo(void);
    > > void destroy_foo(foo *ptr);
    > >
    > > void use_foo(foo *ptr);
    > >
    > > The actual definition of 'struct foo' goes in the source file:
    > >
    > > foo.c
    > > -----
    > > struct foo
    > > {
    > > /* ... */
    > > };
    > >
    > > So that it's only foo.c that knows what the contents of a struct foo
    > > are. The contents are hidden, ie opaque, from everything that merely
    > > includes foo.h - all you can do is pass pointers around.

    >
    > That's wrong.
    > The defintion of the stuct type needs to be in the header file.
    > Otherwise,
    > void destroy_foo(foo *ptr);
    > wouldn't mean anything in the header file.


    In general, it's only object defintions and function definitions
    that don't belong in header files.
    Typedefs and enums are two kinds of definitions
    that are typically OK in header files.

    I'm not too familiar with inline functions.
    I think they can go in header files too,
    but I'm not sure.

    --
    pete
     
    pete, Aug 17, 2006
    #4
  5. pete wrote:
    > Richard Harnden wrote:
    >> chankl wrote:
    >>> Can anyone explain what's an opaque pointer and how it's implemented in
    >>> C?
    >>>
    >>> I read about this concept in the book "C interfaces and
    >>> implementations".
    >>>
    >>> Here's an example from the book (list.h - available from the website):
    >>>
    >>> #define T List_T
    >>>
    >>> typedef struct T *T;
    >>> struct T {
    >>> T rest;
    >>> void *first;
    >>> };
    >>>
    >>> extern T List_append (T list, T tail);
    >>> extern T List_copy (T list);
    >>> extern T List_list (void *x, ...);
    >>> .
    >>> .
    >>> and so on...
    >>>
    >>> It seems the struct behind List_T is now hidden from the application
    >>> using these functions.The contents of List_T cannot be accessed (or
    >>> dereferenced?).
    >>>
    >>> But I don't see why not. If I have access to the header file, wouldn't
    >>> I be able to dereference the contents of the structure? Or am I missing
    >>> the meaning of opaque?
    >>>
    >>> Any answers is much appreciated.
    >>>

    >> In your header file, you'd have something along the lines of:
    >>
    >> foo.h
    >> -----
    >> typedef struct foo foo;
    >>
    >> foo *create_foo(void);
    >> void destroy_foo(foo *ptr);
    >>
    >> void use_foo(foo *ptr);
    >>
    >> The actual definition of 'struct foo' goes in the source file:
    >>
    >> foo.c
    >> -----
    >> struct foo
    >> {
    >> /* ... */
    >> };
    >>
    >> So that it's only foo.c that knows what the contents of a struct foo
    >> are. The contents are hidden, ie opaque, from everything that merely
    >> includes foo.h - all you can do is pass pointers around.

    >
    > That's wrong.
    > The defintion of the stuct type needs to be in the header file.
    > Otherwise,
    > void destroy_foo(foo *ptr);
    > wouldn't mean anything in the header file.

    Only a forward declaration is needed, so the 'content'
    of the struct becomes opaque to users of the implementation
    of foo.h

    With the above foo.h, I can include it and do
    foo *h = create_foo();
    use_foo(h);
    destroy_foo(h);
     
    =?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=, Aug 17, 2006
    #5
  6. "chankl" <> writes:
    > Can anyone explain what's an opaque pointer and how it's implemented in
    > C?
    >
    > I read about this concept in the book "C interfaces and
    > implementations".
    >
    > Here's an example from the book (list.h - available from the website):
    >
    > #define T List_T
    >
    > typedef struct T *T;
    > struct T {
    > T rest;
    > void *first;
    > };
    >
    > extern T List_append (T list, T tail);
    > extern T List_copy (T list);
    > extern T List_list (void *x, ...);
    > .
    > .
    > and so on...


    Ugh. Is that really the code from the book?

    I can't think of any good reason for the macro defining T as List_T.
    It just obfuscates the code.

    Furthermore, it uses the same identifier, T (um, I mean List_T) as the
    tag for the struct and as a typedef for a *pointer* to the same
    struct. So "struct T" is a structure, and "T" is a pointer to that
    same structure.

    > It seems the struct behind List_T is now hidden from the application
    > using these functions.The contents of List_T cannot be accessed (or
    > dereferenced?).
    >
    > But I don't see why not. If I have access to the header file, wouldn't
    > I be able to dereference the contents of the structure? Or am I missing
    > the meaning of opaque?


    Yes, any code that includes that header can access the members of the
    structure.

    If you really want to declare an abstract pointer type, you can make
    it point to an *incomplete* structure type:

    typedef struct hidden *abstract_pointer;

    and hide the actual definition of "struct hidden" inside a source file
    that implements the library.

    You can do this if you want to make it impossible for client code to
    see the innards of your structure. An alternative is to put the
    structure definition in the visible header, and just tell clients not
    to use it. A good example of this is the type FILE in <stdio.h>; the
    documented interface just uses FILE* as an abstract pointer type, but
    client code *could* access the members of the type FILE. In practice,
    this isn't a problem.

    Here's a small example of a library declaring an abstract pointer type
    and hiding the pointed-to type inside the implementation. There are
    three source files, lib.h, lib.c, and main.c.

    Note that this declares a typedef for a pointer type, which is
    *usually* a bad idea. In this case, the client code doesn't make use
    of the fact that it's a pointer. An alternative would be to declare a
    typedef for the hidden struct type, and have the code use an explicit
    pointer type. (It wouldn't be able to declare an object of the
    structure type, since it's incomplete.)

    =============== lib.h ===============
    #ifndef LIB_H
    #define LIB_H

    typedef struct ap_hidden *abstract_pointer;

    abstract_pointer ap_create (char *s);
    char *ap_get (abstract_pointer x);
    void ap_destroy (abstract_pointer x);

    #endif
    ========================================

    =============== lib.c ===============
    #include "lib.h"
    #include <string.h>
    #include <stdlib.h>

    struct ap_hidden {
    char *str;
    };

    abstract_pointer ap_create(char *s)
    {
    struct ap_hidden *const p = malloc(sizeof *p);
    const size_t size = strlen(s) + 1;
    if (p == NULL) {
    return p;
    }
    p->str = malloc(size);
    if (p->str == NULL) {
    free(p);
    return NULL;
    }
    strcpy(p->str, s);
    return p;
    }

    char *ap_get(abstract_pointer x)
    {
    return x->str;
    }

    void ap_destroy(abstract_pointer x)
    {
    if (x == NULL) {
    return;
    }
    free(x->str);
    free(x);
    }
    ========================================

    =============== main.c ===============
    #include "lib.h"
    #include <stdio.h>

    int main(void)
    {
    abstract_pointer x = ap_create("Hello, world");
    if (x == NULL) {
    printf("ap_create() failed\n");
    }
    else {
    printf("ap_create() ok, ap_get(x) --> \"%s\"\n", ap_get(x));
    }
    ap_destroy(x);
    return 0;
    }
    ========================================

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Aug 17, 2006
    #6
  7. chankl

    pemo Guest

    chankl wrote:
    > Can anyone explain what's an opaque pointer and how it's implemented
    > in C?
    >
    > I read about this concept in the book "C interfaces and
    > implementations".
    >
    > Here's an example from the book (list.h - available from the website):
    >
    > #define T List_T
    >
    > typedef struct T *T;
    > struct T {
    > T rest;
    > void *first;
    > };
    >
    > extern T List_append (T list, T tail);
    > extern T List_copy (T list);
    > extern T List_list (void *x, ...);
    > .
    > .
    > and so on...
    >
    > It seems the struct behind List_T is now hidden from the application
    > using these functions.The contents of List_T cannot be accessed (or
    > dereferenced?).
    >
    > But I don't see why not. If I have access to the header file, wouldn't
    > I be able to dereference the contents of the structure? Or am I
    > missing the meaning of opaque?
    >
    > Any answers is much appreciated.


    I seem to remember that Chris Torek had plenty to say on this relatively
    recently [and see his 'previously' too]. So, I'd advise you to search the
    whole of c.l.c for Chris' stuff [always valuable] - Google's you best mate
    here.

    --
    ==============
    *Not a pedant*
    ==============
     
    pemo, Aug 17, 2006
    #7
  8. chankl

    pete Guest

    "Nils O. SelÄsdal" wrote:
    >
    > pete wrote:
    > > Richard Harnden wrote:
    > >> chankl wrote:
    > >>> Can anyone explain what's an opaque pointer and how it's implemented in
    > >>> C?
    > >>>
    > >>> I read about this concept in the book "C interfaces and
    > >>> implementations".
    > >>>
    > >>> Here's an example from the book (list.h - available from the website):
    > >>>
    > >>> #define T List_T
    > >>>
    > >>> typedef struct T *T;
    > >>> struct T {
    > >>> T rest;
    > >>> void *first;
    > >>> };
    > >>>
    > >>> extern T List_append (T list, T tail);
    > >>> extern T List_copy (T list);
    > >>> extern T List_list (void *x, ...);
    > >>> .
    > >>> .
    > >>> and so on...
    > >>>
    > >>> It seems the struct behind List_T is now hidden from the application
    > >>> using these functions.The contents of List_T cannot be accessed (or
    > >>> dereferenced?).
    > >>>
    > >>> But I don't see why not. If I have access to the header file, wouldn't
    > >>> I be able to dereference the contents of the structure? Or am I missing
    > >>> the meaning of opaque?
    > >>>
    > >>> Any answers is much appreciated.
    > >>>
    > >> In your header file, you'd have something along the lines of:
    > >>
    > >> foo.h
    > >> -----
    > >> typedef struct foo foo;
    > >>
    > >> foo *create_foo(void);
    > >> void destroy_foo(foo *ptr);
    > >>
    > >> void use_foo(foo *ptr);
    > >>
    > >> The actual definition of 'struct foo' goes in the source file:
    > >>
    > >> foo.c
    > >> -----
    > >> struct foo
    > >> {
    > >> /* ... */
    > >> };
    > >>
    > >> So that it's only foo.c
    > >> that knows what the contents of a struct foo
    > >> are. The contents are hidden, ie opaque,
    > >> from everything that merely
    > >> includes foo.h - all you can do is pass pointers around.

    > >
    > > That's wrong.
    > > The defintion of the stuct type needs to be in the header file.
    > > Otherwise,
    > > void destroy_foo(foo *ptr);
    > > wouldn't mean anything in the header file.

    > Only a forward declaration is needed, so the 'content'
    > of the struct becomes opaque to users of the implementation
    > of foo.h
    >
    > With the above foo.h, I can include it and do
    > foo *h = create_foo();
    > use_foo(h);
    > destroy_foo(h);


    Thank you.
    I hadn't noticed the typedef line:

    typedef struct foo foo;

    --
    pete
     
    pete, Aug 18, 2006
    #8
  9. chankl

    Guest

    chankl wrote:
    > Can anyone explain what's an opaque pointer and how it's implemented in
    > C?
    >
    > I read about this concept in the book "C interfaces and
    > implementations".
    >
    > Here's an example from the book (list.h - available from the website):
    >
    > #define T List_T
    >
    > typedef struct T *T;
    > struct T {
    > T rest;
    > void *first;
    > };
    >
    > extern T List_append (T list, T tail);
    > extern T List_copy (T list);
    > extern T List_list (void *x, ...);
    > .
    > .
    > and so on...
    >
    > It seems the struct behind List_T is now hidden from the application
    > using these functions.The contents of List_T cannot be accessed (or
    > dereferenced?).
    >
    > But I don't see why not. If I have access to the header file, wouldn't
    > I be able to dereference the contents of the structure? Or am I missing
    > the meaning of opaque?
    >
    > Any answers is much appreciated.


    There are actually several different questions in here.

    One question is about how C works. If you can #include
    the header file, then yes you can indeed dereference
    pointers and access structure members.

    Another question is about what "opaque type" means. Here
    there isn't a single answer, because the term is used in
    two similar but slightly different ways -

    1. a type whose representation should not be accessed
    outside the implementing module

    2. a type whose representation can not be accessed outside
    the implementing module

    Obviously these two usages are related but they are
    different, and that's probably the source of the confusion
    here.

    A third question is, how would one get an #2-style opaque
    type in C. The answer there is to put only a declaration
    in the header file, and define the struct in a .c file,
    as for example -

    /* list.h */
    ...
    typedef struct List_struct *List;

    extern List List_append(List list, List tail);
    extern List List_copy(List list);
    extern List List_list(void *x, ...);
    ...


    /* list.c */
    #include "list.h"

    struct List_struct {
    List rest;
    void *first;
    }

    In either case the intention is that only list.c will
    access the structure members, but now other code can't
    access them because of where the struct itself is defined.

    Note that this approach doesn't work if list.h needs to
    define macros that access some structure members. In
    that case we might still call List an "opaque type",
    only now the meaning is more like the first meaning of
    opaque type, because C doesn't have a way to allow
    macro access but prevent other access.
     
    , Aug 18, 2006
    #9
  10. chankl

    Guest

    chankl wrote:
    > Can anyone explain what's an opaque pointer and how it's implemented in
    > C?


    The other answers given are failrly reasonable. However, I would just
    like to point out that opacity is generally focused on the undetailed
    struct, and not the fact that it has been typedefed to a pointer.
    I.e., the typedef struct List_T * List_T line is redundant and
    unnecessary (and also going to cause C++ compilers to go into fits.)
    You can simply use the expression struct List_T * instead of List_T
    with no ill effect.

    I.e., the pointers are derivative of the overall idea of making opaque
    structs, and the additional typedef is not relevant to the opacity.

    The reason I am pointing this out is that there is an alternative way
    to gaining opacity through straight void * pointers. You might accept
    void * pointers as your ADT handle, and simply cast it to a (struct
    List_T *) inside your implementation. This works just fine, but has
    the disadvantage of losing typesafety (the compiler will not warn you
    when you've mixed up the handles to two different ADTs, if you declare
    them both as void *, for example.) The advantage of using void *, is
    that you can support a primitive kind of runtime polymorphism. I.e.,
    its possible to have an array of void *'s each pointing to a different
    kind of abstract data type, where even this signature can change at
    runtime. Obviously in this case, the details of how exactly you would
    even know what the type of each entry in such an array is what would be
    interesting. This is *probably* beyond what you are interested in at
    this moment, but I just thought I should point it out, since your
    question was about opaque *pointers*.

    --
    Paul Hsieh
    http://www.pobox.com/~qed/
    http://bstring.sf.net/
     
    , Aug 19, 2006
    #10
  11. chankl

    Guest

    wrote:
    > chankl wrote:
    > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > C?

    >
    > The other answers given are failrly reasonable. However, I would just
    > like to point out that opacity is generally focused on the undetailed
    > struct, and not the fact that it has been typedefed to a pointer.
    > I.e., the typedef struct List_T * List_T line is redundant and
    > unnecessary (and also going to cause C++ compilers to go into fits.)
    > You can simply use the expression struct List_T * instead of List_T
    > with no ill effect.
    >
    > I.e., the pointers are derivative of the overall idea of making opaque
    > structs, and the additional typedef is not relevant to the opacity.


    Using a typedef allows client code to know less
    about a type's representation. Thus it is
    relevant to how opaque the type is. Using a
    typedef might be desirable or it might not
    be, but it is relevant.
     
    , Aug 19, 2006
    #11
  12. "pemo" <> wrote in message
    news:ec2s4b$m9j$...
    > chankl wrote:
    > > Can anyone explain what's an opaque pointer and how it's implemented
    > > in C?
    > >
    > > I read about this concept in the book "C interfaces and
    > > implementations".
    > >
    > > Here's an example from the book (list.h - available from the website):
    > >
    > > #define T List_T
    > >
    > > typedef struct T *T;
    > > struct T {
    > > T rest;
    > > void *first;
    > > };
    > >
    > > extern T List_append (T list, T tail);
    > > extern T List_copy (T list);
    > > extern T List_list (void *x, ...);
    > > .
    > > .
    > > and so on...
    > >
    > > It seems the struct behind List_T is now hidden from the application
    > > using these functions.The contents of List_T cannot be accessed (or
    > > dereferenced?).
    > >
    > > But I don't see why not. If I have access to the header file, wouldn't
    > > I be able to dereference the contents of the structure? Or am I
    > > missing the meaning of opaque?
    > >
    > > Any answers is much appreciated.

    >
    > I seem to remember that Chris Torek had plenty to say on this relatively
    > recently [and see his 'previously' too]. So, I'd advise you to search the
    > whole of c.l.c for Chris' stuff [always valuable] - Google's you best mate
    > here.
    >


    http://groups.google.com/group/comp.lang.c/msg/36f2e02efab6b6f1?hl=en
     
    Rod Pemberton, Aug 19, 2006
    #12
  13. chankl

    Guest

    wrote:
    > wrote:
    > > chankl wrote:
    > > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > > C?

    > >
    > > The other answers given are failrly reasonable. However, I would just
    > > like to point out that opacity is generally focused on the undetailed
    > > struct, and not the fact that it has been typedefed to a pointer.
    > > I.e., the typedef struct List_T * List_T line is redundant and
    > > unnecessary (and also going to cause C++ compilers to go into fits.)
    > > You can simply use the expression struct List_T * instead of List_T
    > > with no ill effect.
    > >
    > > I.e., the pointers are derivative of the overall idea of making opaque
    > > structs, and the additional typedef is not relevant to the opacity.

    >
    > Using a typedef allows client code to know less
    > about a type's representation.


    No, the typedef has to be exposed in the header file (or possibly
    somewhere else). But the typedef is just a pointer. This structure is
    essentially exposed even if you don't "look" at the header file.

    For example, you can say List_t x; /*... */ void * p = x; and the
    compiler doesn't complain -- so this is a kind of exposure. Or more
    minimally you can say sizeof (x) without trouble. Compare this with
    struct List_t *x, *y, and try to do this: *x = *y, or sizeof(*x) or
    sizeof(struct List_T). They both lead to compiler errors.

    > [...] Thus it is
    > relevant to how opaque the type is. Using a
    > typedef might be desirable or it might not
    > be, but it is relevant.


    If you were able to somehow *hide* this typedef, and have the typedef
    just magically be there, and somehow turn off its compatibility with
    other pointers and sizeof(), then I would agree with you. But you
    don't have this.

    In fact if you want to truly "opaquify" a pointer, the way to do that,
    is to put it into an opaque struct (or union).

    --
    Paul Hsieh
    http://www.pobox.com/~qed/
    http://bstring.sf.net/
     
    , Aug 19, 2006
    #13
  14. chankl

    CBFalconer Guest

    wrote:
    > wrote:
    >> chankl wrote:

    >
    >>> Can anyone explain what's an opaque pointer and how it's
    >>> implemented in C?

    >>
    >> The other answers given are failrly reasonable. However, I
    >> would just like to point out that opacity is generally focused
    >> on the undetailed struct, and not the fact that it has been
    >> typedefed to a pointer. I.e., the typedef struct List_T * List_T
    >> line is redundant and unnecessary (and also going to cause C++
    >> compilers to go into fits.) You can simply use the expression
    >> struct List_T * instead of List_T with no ill effect.
    >>
    >> I.e., the pointers are derivative of the overall idea of making
    >> opaque structs, and the additional typedef is not relevant to
    >> the opacity.

    >
    > Using a typedef allows client code to know less
    > about a type's representation. Thus it is
    > relevant to how opaque the type is. Using a
    > typedef might be desirable or it might not
    > be, but it is relevant.


    Your last comment is about the only sensible thing in this whole
    thread. The point about opaque pointers is that they allow
    complete hiding of the implementation, thus preserving the freedom
    to modify without harming the usability. Let's take an example:

    /* foolib.h contains */
    typedef struct foo *fooptr;

    fooptr fooinit(/* various params */);
    void fookill(fooptr fooid);
    int fooscan(fooptr fooid);
    int fooinsert(fooptr fooid, int item);
    int foodelete(fooptr fooid, int item);

    Note that anything that #includes foolib.h will be able to declare
    a fooptr, get a value for that by calling fooinit, and then use the
    system by passing that fooptr back to any functions it calls. The
    user has no idea what is in a "struct foo", yet that struct will
    usually have been malloced and exist in the users memory space.

    This has various advantages. For one, the library can be fully
    re-entrant, provided the passed in fooids are distinct. Thus no
    extra code is needed for multiple instances. The library
    maintainer is completely free to revise the code (but not
    foolib.h), algorithms, etc. used without affecting the user code in
    any way. There is no way for a user to affect the internals of the
    foolib, other than by random chance probing into a struct foo, so
    the library integrity is assured (as far as possible with the C
    language). The actual struct foo will probably store a description
    of the state of the foolib, including things related to the
    initializing parameters supplied via fooinit.

    Note that the actual definition of a "struct foo" occurs only
    within foolib.c and is never published. Any functions, other than
    those prototyped in foolib.h, will be declared as static so that
    they are inaccessible from outside foolib.c. foolib.c will
    probably contain no globals, nor global references, to ensure
    re-entrancy.

    --
    "The power of the Executive to cast a man into prison without
    formulating any charge known to the law, and particularly to
    deny him the judgement of his peers, is in the highest degree
    odious and is the foundation of all totalitarian government
    whether Nazi or Communist." -- W. Churchill, Nov 21, 1943
     
    CBFalconer, Aug 19, 2006
    #14
  15. chankl

    Guest

    CBFalconer wrote:
    > wrote:
    > > wrote:
    > >> chankl wrote:

    > >
    > >>> Can anyone explain what's an opaque pointer and how it's
    > >>> implemented in C?
    > >>
    > >> The other answers given are failrly reasonable. However, I
    > >> would just like to point out that opacity is generally focused
    > >> on the undetailed struct, and not the fact that it has been
    > >> typedefed to a pointer. I.e., the typedef struct List_T * List_T
    > >> line is redundant and unnecessary (and also going to cause C++
    > >> compilers to go into fits.) You can simply use the expression
    > >> struct List_T * instead of List_T with no ill effect.
    > >>
    > >> I.e., the pointers are derivative of the overall idea of making
    > >> opaque structs, and the additional typedef is not relevant to
    > >> the opacity.

    > >
    > > Using a typedef allows client code to know less
    > > about a type's representation. Thus it is
    > > relevant to how opaque the type is. Using a
    > > typedef might be desirable or it might not
    > > be, but it is relevant.

    >
    > Your last comment is about the only sensible thing in this whole
    > thread. The point about opaque pointers is that they allow
    > complete hiding of the implementation, thus preserving the freedom
    > to modify without harming the usability. Let's take an example:
    >
    > /* foolib.h contains */
    > typedef struct foo *fooptr;
    >
    > fooptr fooinit(/* various params */);
    > void fookill(fooptr fooid);
    > int fooscan(fooptr fooid);
    > int fooinsert(fooptr fooid, int item);
    > int foodelete(fooptr fooid, int item);
    >
    > Note that anything that #includes foolib.h will be able to declare
    > a fooptr, get a value for that by calling fooinit, and then use the
    > system by passing that fooptr back to any functions it calls. The
    > user has no idea what is in a "struct foo", yet that struct will
    > usually have been malloced and exist in the users memory space.
    >
    > This has various advantages. For one, the library can be fully
    > re-entrant, provided the passed in fooids are distinct. Thus no
    > extra code is needed for multiple instances. The library
    > maintainer is completely free to revise the code (but not
    > foolib.h), algorithms, etc. used without affecting the user code in
    > any way. There is no way for a user to affect the internals of the
    > foolib, other than by random chance probing into a struct foo, so
    > the library integrity is assured (as far as possible with the C
    > language). The actual struct foo will probably store a description
    > of the state of the foolib, including things related to the
    > initializing parameters supplied via fooinit.
    >
    > Note that the actual definition of a "struct foo" occurs only
    > within foolib.c and is never published. Any functions, other than
    > those prototyped in foolib.h, will be declared as static so that
    > they are inaccessible from outside foolib.c. foolib.c will
    > probably contain no globals, nor global references, to ensure
    > re-entrancy.Basically I agree with everything you've said here.


    The points we're making are in somewhat different
    realms. Technically C doesn't have opaque types,
    rather it has some characteristics that allow us
    to make types that we can think of as opaque.
    Your comments show one way of doing this, and
    list some advantages of using this approach.
    I concur that this method has these kinds of
    advantages.
     
    , Aug 24, 2006
    #15
  16. chankl

    Guest

    wrote:
    > wrote:
    > > wrote:
    > > > chankl wrote:
    > > > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > > > C?
    > > >
    > > > The other answers given are failrly reasonable. However, I would just
    > > > like to point out that opacity is generally focused on the undetailed
    > > > struct, and not the fact that it has been typedefed to a pointer.
    > > > I.e., the typedef struct List_T * List_T line is redundant and
    > > > unnecessary (and also going to cause C++ compilers to go into fits.)
    > > > You can simply use the expression struct List_T * instead of List_T
    > > > with no ill effect.
    > > >
    > > > I.e., the pointers are derivative of the overall idea of making opaque
    > > > structs, and the additional typedef is not relevant to the opacity.

    > >
    > > Using a typedef allows client code to know less
    > > about a type's representation.

    >
    > No, the typedef has to be exposed in the header file (or possibly
    > somewhere else). But the typedef is just a pointer. This structure is
    > essentially exposed even if you don't "look" at the header file.


    When I say a typedef "allows client code to know less"
    what I mean is code can be written that doesn't depend
    on the types representation. Not that it _can't_ be
    written to depend on the representation, but that
    it _can_ be written so that it _doesn't_ depend.
    That's an important property, and using typedef
    enables that.

    > For example, you can say List_t x; /*... */ void * p = x; and the
    > compiler doesn't complain -- so this is a kind of exposure. Or more
    > minimally you can say sizeof (x) without trouble. Compare this with
    > struct List_t *x, *y, and try to do this: *x = *y, or sizeof(*x) or
    > sizeof(struct List_T). They both lead to compiler errors.


    That's true but irrelevant to the point I'm making.

    > > [...] Thus it is
    > > relevant to how opaque the type is. Using a
    > > typedef might be desirable or it might not
    > > be, but it is relevant.

    >
    > If you were able to somehow *hide* this typedef, and have the typedef
    > just magically be there, and somehow turn off its compatibility with
    > other pointers and sizeof(), then I would agree with you. But you
    > don't have this.
    >
    > In fact if you want to truly "opaquify" a pointer, the way to do that,
    > is to put it into an opaque struct (or union).


    To be technically accurate, C doesn't have opaque types.
    The standard doesn't mention them, and there is no construct
    in C that produces a type that is 'opaque' in the sense
    that the term is used in languages that have opaque types
    incorporated into the language.

    Rather, what C has is ways of making types that we
    can _think of_ as opaque. Using typedef is one way
    of doing this. Putting a struct definition in
    a source file rather than a header file is another
    way. Wrapping the representation inside a struct
    and using only the struct in client code is another
    way. Each of these ways may offer certain advantages
    or disadvantages, but none of them creates a type
    that is truly opaque, only a type that is convenient
    to think of as opaque. That's why using typedef
    is relevant to the notion of opaque types in C.
     
    , Aug 24, 2006
    #16
  17. chankl

    Guest

    wrote:
    > wrote:
    > > wrote:
    > > > wrote:
    > > > > chankl wrote:
    > > > > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > > > > C?
    > > > >
    > > > > The other answers given are failrly reasonable. However, I would just
    > > > > like to point out that opacity is generally focused on the undetailed
    > > > > struct, and not the fact that it has been typedefed to a pointer.
    > > > > I.e., the typedef struct List_T * List_T line is redundant and
    > > > > unnecessary (and also going to cause C++ compilers to go into fits.)
    > > > > You can simply use the expression struct List_T * instead of List_T
    > > > > with no ill effect.
    > > > >
    > > > > I.e., the pointers are derivative of the overall idea of making opaque
    > > > > structs, and the additional typedef is not relevant to the opacity.
    > > >
    > > > Using a typedef allows client code to know less
    > > > about a type's representation.

    > >
    > > No, the typedef has to be exposed in the header file (or possibly
    > > somewhere else). But the typedef is just a pointer. This structure is
    > > essentially exposed even if you don't "look" at the header file.

    >
    > When I say a typedef "allows client code to know less"
    > what I mean is code can be written that doesn't depend
    > on the types representation.


    But the same would be true if you used, say, a #define to try to "hide"
    the definition as well.

    > [...] Not that it _can't_ be
    > written to depend on the representation, but that
    > it _can_ be written so that it _doesn't_ depend.


    But that's totally nonsense. If you actively avoid such direct access,
    then it doesn't matter whether you've hidden the definition or not.
    The point of using real language support for opacity is to have the
    compiler work with you in enforcing such opacity. Some might consider
    this a part of what it means to have strong typing.

    > That's an important property, and using typedef
    > enables that.


    Except that this doesn't distinguish itself from #defines which can
    accomplish the same thing.

    > > For example, you can say List_t x; /*... */ void * p = x; and the
    > > compiler doesn't complain -- so this is a kind of exposure. Or more
    > > minimally you can say sizeof (x) without trouble. Compare this with
    > > struct List_t *x, *y, and try to do this: *x = *y, or sizeof(*x) or
    > > sizeof(struct List_T). They both lead to compiler errors.

    >
    > That's true but irrelevant to the point I'm making.


    I'm sure it is -- but it seems to me that its your point which is less
    relevant to the topic of real opacity.

    > > > [...] Thus it is
    > > > relevant to how opaque the type is. Using a
    > > > typedef might be desirable or it might not
    > > > be, but it is relevant.

    > >
    > > If you were able to somehow *hide* this typedef, and have the typedef
    > > just magically be there, and somehow turn off its compatibility with
    > > other pointers and sizeof(), then I would agree with you. But you
    > > don't have this.
    > >
    > > In fact if you want to truly "opaquify" a pointer, the way to do that,
    > > is to put it into an opaque struct (or union).

    >
    > To be technically accurate, C doesn't have opaque types.
    > The standard doesn't mention them, [...]


    Ok, now you are slipping into Keith Thompson mode. Just because the
    standard does not explicitely use the language, doesn't mean the thing
    isn't there. C *DOES* contain the following: variables, a stack and a
    heap (or dynamic memory pool), regardless of what the standard says
    (even if the implementation of the later two are not specified).
    That's because all those are general concepts that the C language has
    support for, even if not spelled out in the specification. Similarly,
    my computer has the ability to factor large integers even though none
    of its specifications explicitely say that it can do that.

    Same is true of opacity. C isn't missing opacity because it doesn't
    discuss it in the standard. Opacity is merely a *property* of certain
    declarations (structs and unions that are not fully specified and void
    * pointers). This is a real concept because of how it dictates the
    interaction between *two* programmers. If one programmer makes an
    opaque type, then another cannot normally gain access to its explicit
    definition, and this is enforced (more like 'supported' for void *'s)
    by the compiler/language. So the two programmers don't even have to
    contact each other to understand how things are supposed to be used.
    On the other hand, if one is simply relying on typedef, the other
    programmer can just read the header file see that its a typedef and
    just go ahead and do things like handle->privateEntry (unless real
    opacity via a struct or union is in there).

    > [...] and there is no construct
    > in C that produces a type that is 'opaque' in the sense
    > that the term is used in languages that have opaque types
    > incorporated into the language.


    Obviously every language puts a slightly different spin on things
    (compare tables in Lua with tables in TCL with Dictionaries in Python
    with hashes in Perl; or coroutines in Lua versus generators in Python).
    C's main weakness is that an "opaque type" can be *falsely* redefined
    anyways -- but doing so, is an explicit subversion of intent, and
    should not be a problem in real practice (assuming you are doing things
    in good faith -- i.e., avoid the void * method, and don't ever define
    any struct/union in more than one file). Other languages are likely to
    have tougher enforcement, but the main concepts are the same.

    > Rather, what C has is ways of making types that we
    > can _think of_ as opaque.


    If such mechanisms exist primarily in your mind, then they apply
    equally to all other languages, and exposed mechanisms from any data
    type anywhere. There is nothing special about typedef which
    corresponds to one's "thinking". If you are just one programmer, its
    not a problem at all to "think" about certain data types as being
    opaque in certain contexts regardless of what the real state is --
    typedef has nothing to do with this.

    There is a big difference between opacity enforced by a compiler and
    opacity conceptualized through convention. And this is most critically
    seen as the number of developers on a project increases.

    --
    Paul Hsieh
    http://www.pobox.com/~qed/
    http://bstring.sf.net/
     
    , Aug 24, 2006
    #17
  18. chankl

    Guest

    wrote:
    > wrote:
    > > wrote:
    > > > wrote:
    > > > > wrote:
    > > > > > chankl wrote:
    > > > > > > Can anyone explain what's an opaque pointer and how it's implemented in
    > > > > > > C?
    > > > > >
    > > > > > The other answers given are failrly reasonable. However, I would just
    > > > > > like to point out that opacity is generally focused on the undetailed
    > > > > > struct, and not the fact that it has been typedefed to a pointer.
    > > > > > I.e., the typedef struct List_T * List_T line is redundant and
    > > > > > unnecessary (and also going to cause C++ compilers to go into fits.)
    > > > > > You can simply use the expression struct List_T * instead of List_T
    > > > > > with no ill effect.
    > > > > >
    > > > > > I.e., the pointers are derivative of the overall idea of making opaque
    > > > > > structs, and the additional typedef is not relevant to the opacity.
    > > > >
    > > > > Using a typedef allows client code to know less
    > > > > about a type's representation.
    > > >
    > > > No, the typedef has to be exposed in the header file (or possibly
    > > > somewhere else). But the typedef is just a pointer. This structure is
    > > > essentially exposed even if you don't "look" at the header file.

    > >
    > > When I say a typedef "allows client code to know less"
    > > what I mean is code can be written that doesn't depend
    > > on the types representation.

    >
    > But the same would be true if you used, say, a #define to try to "hide"
    > the definition as well.


    Yes, that is another technique, although using typedef
    is usually better.

    > > [...] Not that it _can't_ be
    > > written to depend on the representation, but that
    > > it _can_ be written so that it _doesn't_ depend.

    >
    > But that's totally nonsense. If you actively avoid such direct access,
    > then it doesn't matter whether you've hidden the definition or not.


    Suppose the type in question is an unsigned int. If there is no
    typedef, then client code declaring variables of the type
    would use

    unsigned xyz;

    If later we wanted to change the representation to be
    a pointer rather than an unsigned, then client code
    would need to be changed to accommodate the new type.

    If typedef had been used, no client code would need to
    be changed; the client code doesn't depend on what
    underlying type is used to represent the type name.

    > The point of using real language support for opacity is to have the
    > compiler work with you in enforcing such opacity. [...]


    That is one aspect of opaque types but not the only
    aspect.

    > > That's an important property, and using typedef
    > > enables that.

    >
    > Except that this doesn't distinguish itself from #defines which can
    > accomplish the same thing.


    Perhaps you need to review the differences between

    typedef struct foo_struct *Foo;

    and

    #define Foo struct foo_struct *

    which, although they both define Foo, cannot be
    used interchangeably.

    > > > For example, you can say List_t x; /*... */ void * p = x; and the
    > > > compiler doesn't complain -- so this is a kind of exposure. Or more
    > > > minimally you can say sizeof (x) without trouble. Compare this with
    > > > struct List_t *x, *y, and try to do this: *x = *y, or sizeof(*x) or
    > > > sizeof(struct List_T). They both lead to compiler errors.

    > >
    > > That's true but irrelevant to the point I'm making.

    >
    > I'm sure it is -- but it seems to me that its your point which is less
    > relevant to the topic of real opacity.


    You have a narrow view of what it means to program
    using "opaque types". You're welcome to your view,
    but it isn't the only view.

    > > > > [...] Thus it is
    > > > > relevant to how opaque the type is. Using a
    > > > > typedef might be desirable or it might not
    > > > > be, but it is relevant.
    > > >
    > > > If you were able to somehow *hide* this typedef, and have the typedef
    > > > just magically be there, and somehow turn off its compatibility with
    > > > other pointers and sizeof(), then I would agree with you. But you
    > > > don't have this.
    > > >
    > > > In fact if you want to truly "opaquify" a pointer, the way to do that,
    > > > is to put it into an opaque struct (or union).

    > >
    > > To be technically accurate, C doesn't have opaque types.
    > > The standard doesn't mention them, [...]

    >
    > Ok, now you are slipping into Keith Thompson mode. [...]


    Oh, a compliment - thank you! Would I be returning the
    favor if I said you were slipping into websnarf mode?

    > > Rather, what C has is ways of making types that we
    > > can _think of_ as opaque.

    >
    > If such mechanisms exist primarily in your mind, then they apply
    > equally to all other languages, and exposed mechanisms from any data
    > type anywhere. There is nothing special about typedef which
    > corresponds to one's "thinking". [...]


    If you say there isn't for you, I have no problem
    with that. Not everyone shares your viewpoint, however.

    > There is a big difference between opacity enforced by a compiler and
    > opacity conceptualized through convention. And this is most critically
    > seen as the number of developers on a project increases.


    I wasn't arguing the relative merits, only saying that
    using typedef is relevant to the notion of opaque types
    in C. Using typedef facilitates one kind of advantages;
    using hidden struct definitions facilitates another kind
    of advantages. Both kinds relate to opaque types.
     
    , Aug 24, 2006
    #18
  19. On Sat, 19 Aug 2006 10:01:35 -0400, CBFalconer <>
    wrote:
    <snip>
    > Your last comment is about the only sensible thing in this whole
    > thread. The point about opaque pointers is that they allow
    > complete hiding of the implementation, thus preserving the freedom
    > to modify without harming the usability. Let's take an example:
    >
    > /* foolib.h contains */
    > typedef struct foo *fooptr;
    >
    > fooptr fooinit(/* various params */);

    <snip etc.>

    > This has various advantages. For one, the library can be fully
    > re-entrant, provided the passed in fooids are distinct. Thus no
    > extra code is needed for multiple instances. The library


    That is not an advantage for this technique; it is equally possible
    with nonopaque types. In both cases, as you indicate later, it
    requires some care, and is not an inherent property.

    > maintainer is completely free to revise the code (but not
    > foolib.h), algorithms, etc. used without affecting the user code in


    In theory. In practice, at least if foolib is substantial in
    functionality and significantly used, at least some clients tend to
    become dependent on properties additional to those in the (rather
    limited) C specification of the interface -- and get very upset if
    broken by an implementation change. However, even being
    _substantially_ free to change the library without _any_ change to
    clients is A Good Thing (tm) and usually Worth It (tm).

    Aside: who was it used to trademark words like this? I've forgotten.

    > any way. There is no way for a user to affect the internals of the
    > foolib, other than by random chance probing into a struct foo, so
    > the library integrity is assured (as far as possible with the C
    > language.) <snip>


    Agree, with the sadly-too-important qualification you gave, plus
    another: if foolib depends on some process (or wider) resource(s) also
    accessible to the client, or for that matter barlib. Obvious and
    too-common examples are things like: using up memory; (mis)using fds
    or other capabilities like sockets; changing the locale, or working
    directory, or alarm timer(s). But again, pretty-good isolation well
    short of perfect is still a good deal better than nothing.


    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Aug 28, 2006
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. dna
    Replies:
    0
    Views:
    1,232
  2. Martin Meier

    opaque - Bedeutung ?

    Martin Meier, Sep 10, 2004, in forum: Java
    Replies:
    3
    Views:
    1,503
    Eric Sosman
    Sep 10, 2004
  3. jashugun

    static opaque pointers?

    jashugun, Feb 5, 2006, in forum: C++
    Replies:
    2
    Views:
    384
    jashugun
    Feb 5, 2006
  4. =?iso-8859-1?q?Ernesto_Basc=F3n?=

    Opaque pointers, templates and ABCs

    =?iso-8859-1?q?Ernesto_Basc=F3n?=, Oct 25, 2006, in forum: C++
    Replies:
    3
    Views:
    404
    Roland Pibinger
    Oct 25, 2006
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    737
Loading...

Share This Page