inline function or macro?

Discussion in 'C Programming' started by jacob navia, Jan 2, 2010.

  1. jacob navia

    jacob navia Guest

    One situation where macros are the only solution, and inline functions
    just do not cut it is when you have several structures that share a
    common field, and you want to access it without a function call.

    For instance in a container library (strange, what a coincidence :) )
    all the containers share the "count" field, that access the number of
    elements in the container.

    Here it would be impossible to use an inline function since all the
    containers are different types. A macro is the only solution:

    #define GetCount(container) (container->count)

    This will work with all containers. Unless you use lcc-win and have
    true generic functions (or use C++) the macro is the only really
    portable solution.
     
    jacob navia, Jan 2, 2010
    #1
    1. Advertising

  2. jacob navia

    Nick Guest

    jacob navia <> writes:

    > One situation where macros are the only solution, and inline functions
    > just do not cut it is when you have several structures that share a
    > common field, and you want to access it without a function call.
    >
    > For instance in a container library (strange, what a coincidence :) )
    > all the containers share the "count" field, that access the number of
    > elements in the container.
    >
    > Here it would be impossible to use an inline function since all the
    > containers are different types. A macro is the only solution:
    >
    > #define GetCount(container) (container->count)
    >
    > This will work with all containers. Unless you use lcc-win and have
    > true generic functions (or use C++) the macro is the only really
    > portable solution.


    Although I've done this myself (even when not needing to work on generic
    structures; for example my dynamic strings have dstr(x) to get the
    c-string from x and dstrlen(x) to get the length; each of these is just
    a macro to hide access to a member of the structure), at the back of my
    mind I'm not entirely convinced by it.

    After all, container->count is every bit as readable as
    GetCount(container) and it's actually more like the syntax in other
    popular languages (where it could be container.count). The benefit of
    using a (probably not inline) function to get the field is that you can
    then hide the structure away inside the library and not expose it to the
    user. With the macro you're exposing everything, you're just not
    documenting it. So why not just document only the fields the user is
    allowed to change, and let them do it using standard syntax.

    After all, there's nothing the macro does to prevent the user from doing
    GetCount(container) = 18;
    --
    Online waterways route planner | http://canalplan.eu
    Plan trips, see photos, check facilities | http://canalplan.org.uk
     
    Nick, Jan 2, 2010
    #2
    1. Advertising

  3. Nick wrote :
    > jacob navia <> writes:
    >
    >> One situation where macros are the only solution, and inline functions
    >> just do not cut it is when you have several structures that share a
    >> common field, and you want to access it without a function call.
    >>
    >> For instance in a container library (strange, what a coincidence :) )
    >> all the containers share the "count" field, that access the number of
    >> elements in the container.
    >>
    >> Here it would be impossible to use an inline function since all the
    >> containers are different types. A macro is the only solution:
    >>
    >> #define GetCount(container) (container->count)
    >>
    >> This will work with all containers. Unless you use lcc-win and have
    >> true generic functions (or use C++) the macro is the only really
    >> portable solution.

    >
    > Although I've done this myself (even when not needing to work on generic
    > structures; for example my dynamic strings have dstr(x) to get the
    > c-string from x and dstrlen(x) to get the length; each of these is just
    > a macro to hide access to a member of the structure), at the back of my
    > mind I'm not entirely convinced by it.
    >
    > After all, container->count is every bit as readable as
    > GetCount(container) and it's actually more like the syntax in other
    > popular languages (where it could be container.count). The benefit of
    > using a (probably not inline) function to get the field is that you can
    > then hide the structure away inside the library and not expose it to the
    > user. With the macro you're exposing everything, you're just not
    > documenting it. So why not just document only the fields the user is
    > allowed to change, and let them do it using standard syntax.
    >
    > After all, there's nothing the macro does to prevent the user from doing
    > GetCount(container) = 18;


    This could be solved by
    #define GetCount(container) ((int)(container->count))

    Francois Grieu
     
    Francois Grieu, Jan 2, 2010
    #3
  4. I wrote
    #define GetCount(container) ((int)(container->count))

    but now I'm leaning towards
    #define GetCount(container) (1?0:container->count))
     
    Francois Grieu, Jan 2, 2010
    #4
  5. jacob navia

    Ike Naar Guest

    In article <4b3f4f11$0$2027$>,
    Francois Grieu <> wrote:
    >I wrote
    >#define GetCount(container) ((int)(container->count))
    >
    >but now I'm leaning towards
    >#define GetCount(container) (1?0:container->count))


    Are you sure?
     
    Ike Naar, Jan 2, 2010
    #5
  6. jacob navia

    Nick Guest

    Francois Grieu <> writes:

    > I wrote
    > #define GetCount(container) ((int)(container->count))
    >
    > but now I'm leaning towards
    > #define GetCount(container) (1?0:container->count))


    Apart from the syntax error of course!

    How about
    #define GetCount(container) (0+container->count)
    assuming count is a number of some sort (it had better be!). Plus a
    comment to explain why you are doing this.
    --
    Online waterways route planner | http://canalplan.eu
    Plan trips, see photos, check facilities | http://canalplan.org.uk
     
    Nick, Jan 2, 2010
    #6
  7. Ike Naar a écrit :
    > In article <4b3f4f11$0$2027$>,
    > Francois Grieu <> wrote:
    >> I wrote
    >> #define GetCount(container) ((int)(container->count))
    >>
    >> but now I'm leaning towards
    >> #define GetCount(container) (1?0:container->count))

    >
    > Are you sure?


    No. That's why I (tried to) cancel the post.
    #define GetCount(container) (1?0:container->count)

    Francois Grieu
     
    Francois Grieu, Jan 2, 2010
    #7
  8. jacob navia

    Eric Sosman Guest

    On 1/2/2010 4:41 AM, jacob navia wrote:
    > One situation where macros are the only solution, and inline functions
    > just do not cut it is when you have several structures that share a
    > common field, and you want to access it without a function call.
    >
    > For instance in a container library (strange, what a coincidence :) )
    > all the containers share the "count" field, that access the number of
    > elements in the container.
    >
    > Here it would be impossible to use an inline function since all the
    > containers are different types. A macro is the only solution:
    >
    > #define GetCount(container) (container->count)
    >
    > This will work with all containers. Unless you use lcc-win and have
    > true generic functions (or use C++) the macro is the only really
    > portable solution.


    "Only?"

    typedef struct {
    size_t count;
    nobili_t baron;
    royal_t duke;
    } AllContainersHaveThis;

    typedef struct {
    AllContainersHaveThis common;
    vani_t all_is;
    } ContainerOne;

    typedef struct {
    AllContainersHaveThis common;
    varie_t spice_of_life;
    } ContainerTwo;

    typedef struct {
    AllContainersHaveThis common;
    portabili_t too_heavy_to_carry;
    } ContainerThree;

    Or you can "turn it inside out:"

    typedef struct {
    vani_t all_is;
    } OneSpecial;

    typedef struct {
    varie_t spice_of_life;
    } TwoSpecial;

    typedef struct {
    portabili_t too_heavy_to_carry;
    } ThreeSpecial;

    typedef struct {
    size_t count;
    nobili_t baron;
    royal_t duke;
    union {
    OneSpecial one;
    TwoSpecial two;
    ThreeSpecial three;
    } specialization;
    } Container;

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 2, 2010
    #8
  9. jacob navia

    Ike Naar Guest

    In article <4b3f58d5$0$30451$>,
    Francois Grieu <> wrote:
    >Ike Naar a écrit :
    >> In article <4b3f4f11$0$2027$>,
    >> Francois Grieu <> wrote:
    >>> I wrote
    >>> #define GetCount(container) ((int)(container->count))
    >>>
    >>> but now I'm leaning towards
    >>> #define GetCount(container) (1?0:container->count))

    >>
    >> Are you sure?

    >
    >No. That's why I (tried to) cancel the post.
    >#define GetCount(container) (1?0:container->count)


    It still seems wrong. I think you mean
    #define GetCount(container) (0 ? 0 : (container)->count)
     
    Ike Naar, Jan 2, 2010
    #9
  10. jacob navia

    jacob navia Guest

    Eric Sosman a écrit :
    >
    > typedef struct {
    > size_t count;
    > nobili_t baron;
    > royal_t duke;
    > } AllContainersHaveThis;
    >
    > typedef struct {
    > AllContainersHaveThis common;
    > vani_t all_is;
    > } ContainerOne;
    >
    > typedef struct {
    > AllContainersHaveThis common;
    > varie_t spice_of_life;
    > } ContainerTwo;
    >
    > typedef struct {
    > AllContainersHaveThis common;
    > portabili_t too_heavy_to_carry;
    > } ContainerThree;
    >


    Sure, but then the access is
    container->common.count;
    and not
    container->count;
    what is easier on the user.

    > Or you can "turn it inside out:"
    >
    > typedef struct {
    > vani_t all_is;
    > } OneSpecial;
    >
    > typedef struct {
    > varie_t spice_of_life;
    > } TwoSpecial;
    >
    > typedef struct {
    > portabili_t too_heavy_to_carry;
    > } ThreeSpecial;
    >
    > typedef struct {
    > size_t count;
    > nobili_t baron;
    > royal_t duke;
    > union {
    > OneSpecial one;
    > TwoSpecial two;
    > ThreeSpecial three;
    > } specialization;
    > } Container;
    >


    True, that is possible too, but then the access to the vtable
    is even longer. Instead of
    container->lpVtble->Add(container,"foo");
    you would have
    container->one->lpVtbl->Add(container,"Foo");

    It is already difficult to have to type the first form, an even
    more verbose access would be really bad...


    Another thing would be to use the preprocessor

    typedef strucy newContainer {
    #include "commonfields.h"
    int extrafield;
    int *data;
    };

    But this doesn't really help a lot.
     
    jacob navia, Jan 2, 2010
    #10
  11. jacob navia

    spinoza1111 Guest

    On Jan 2, 5:41 pm, jacob navia <> wrote:
    > One situation where macros are the only solution, and inline functions
    > just do not cut it is when you have several structures that share a
    > common field, and you want to access it without a function call.
    >
    > For instance in a container library (strange, what a coincidence :) )
    > all the containers share the "count" field, that access the number of
    > elements in the container.
    >
    > Here it would be impossible to use an inline function since all the
    > containers are different types. A macro is the only solution:
    >
    > #define GetCount(container) (container->count)
    >
    > This will work with all containers. Unless you use lcc-win and have
    > true generic functions (or use C++) the macro is the only really
    > portable solution.


    Yes, but that is why generics were added to .Net.

    public static class containerTools<containerType>
    {
    public static int getCount(containerType container)
    {
    return container.count;
    }
    }

    Simple, right?

    There is a problem in your code. If container is an expression, the ->
    may associate incorrectly. A well known fix that you probably know
    would be to code

    #define GetCount(container) ((container)->count)

    unless I'm missing something.

    Also, if container doesn't have a count, the emitted code won't
    compile. I understand that this is true for macros in general. Either
    the macro is well-documented, or you can see its code as in a white or
    transparent box.

    Lacking Turing-complete conditional assembly and a richer set of
    functions which have long been available in languages such as
    assembler, the macro is not able to validate its own parameters,
    whereas I was able to do this in the macro language of IBM BAL. Even
    if a C preprocessor could detect many errors, it has no way of
    informing the user save a crude hack such as generating a printf()
    that waits until runtime to say "you made an error"!

    Now, a colleague whose name I won't mention in a probably futile
    effort to make sure he stays away thinks that "macro processing" and
    "conditional compilation" are two separate things: but in fact, when
    you finish mere textual substitution, you're not done, since you
    cannot error check parameters. This in fact was why almost as soon as
    simple textual macros appeared in IBM assemblers of the 1950s, they
    had to be enhanced with conditional compilation, the ability to emit
    diagnostics and even crude loops that used macro-expansion-time Go Tos
    to create loops. They were Turing-complete.

    Have you considered, Mr Navia, replacing the C preprocessor with such
    a macro processor, since you appear to be in the (too me rather
    *maudit*) business of trying to make a sensible language out of C?

    But: note that far more work is needed in C to get to the purse of
    silk from the ear of sow or tongue of bat or eye of newt stage that it
    appears to me C is stuck in.
     
    spinoza1111, Jan 2, 2010
    #11
  12. jacob navia

    Eric Sosman Guest

    On 1/2/2010 12:39 PM, jacob navia wrote:
    > Eric Sosman a écrit :
    >>
    >> typedef struct {
    >> size_t count;
    >> nobili_t baron;
    >> royal_t duke;
    >> } AllContainersHaveThis;
    >> [...]

    >
    > Sure, but then the access is
    > container->common.count;
    > and not
    > container->count;
    > what is easier on the user.


    If you can do `container->count', why bother with
    your `GetCount(container)' macro in the first place?
    What problem are you trying to solve?

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 2, 2010
    #12
  13. jacob navia

    jacob navia Guest

    Eric Sosman a écrit :
    > On 1/2/2010 12:39 PM, jacob navia wrote:
    >> Eric Sosman a écrit :
    >>>
    >>> typedef struct {
    >>> size_t count;
    >>> nobili_t baron;
    >>> royal_t duke;
    >>> } AllContainersHaveThis;
    >>> [...]

    >>
    >> Sure, but then the access is
    >> container->common.count;
    >> and not
    >> container->count;
    >> what is easier on the user.

    >
    > If you can do `container->count', why bother with
    > your `GetCount(container)' macro in the first place?
    > What problem are you trying to solve?
    >


    I would prefer not to let users use "->count" directly in case
    I need to change it later, because, for instance, capitalization
    problems, (Count or count?), or because it is better to call
    it NumberOfEelemnts, etc.

    But not ALL members of the common subset have macros for them
    since I want to avoid using common names as much as possible.

    The GetCount macro is on by default, but if it collides with
    one name in your name space you should be able to disable it.

    As you know, C has no "hidden/protected" structure members.
     
    jacob navia, Jan 2, 2010
    #13
  14. jacob navia

    Eric Sosman Guest

    On 1/2/2010 1:57 PM, jacob navia wrote:
    > Eric Sosman a écrit :
    >> On 1/2/2010 12:39 PM, jacob navia wrote:
    >>> Eric Sosman a écrit :
    >>>>
    >>>> typedef struct {
    >>>> size_t count;
    >>>> nobili_t baron;
    >>>> royal_t duke;
    >>>> } AllContainersHaveThis;
    >>>> [...]
    >>>
    >>> Sure, but then the access is
    >>> container->common.count;
    >>> and not
    >>> container->count;
    >>> what is easier on the user.

    >>
    >> If you can do `container->count', why bother with
    >> your `GetCount(container)' macro in the first place?
    >> What problem are you trying to solve?
    >>

    >
    > I would prefer not to let users use "->count" directly in case
    > I need to change it later, because, for instance, capitalization
    > problems, (Count or count?), or because it is better to call
    > it NumberOfEelemnts, etc.


    If the users aren't supposed to access `count' directly,
    why object that `container->count' is "easier on the user" than
    `container->common.count'? Neither form will be used at all,
    so why prefer one as "easier" than the other?

    I still don't get it ...

    > But not ALL members of the common subset have macros for them
    > since I want to avoid using common names as much as possible.


    Sorry: I don't understand this at all. I imagine this is
    because I lack a good deal of context, design and implementation
    details that reside in your head but not in mine.

    > The GetCount macro is on by default, but if it collides with
    > one name in your name space you should be able to disable it.


    And thus give up the ability to find out how many elements
    a container holds? I still *really* don't get it ...

    > As you know, C has no "hidden/protected" structure members.


    No. It's all or nothing: Expose all of a struct's elements,
    or make the whole struct an incomplete type and hide everything.
    (For an abstract data type like "container," the latter seems
    such a natural choice that I don't understand why you avoid it.)

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jan 2, 2010
    #14
  15. jacob navia <> writes:
    > One situation where macros are the only solution, and inline functions
    > just do not cut it is when you have several structures that share a
    > common field, and you want to access it without a function call.
    >
    > For instance in a container library (strange, what a coincidence :) )
    > all the containers share the "count" field, that access the number of
    > elements in the container.
    >
    > Here it would be impossible to use an inline function since all the
    > containers are different types. A macro is the only solution:
    >
    > #define GetCount(container) (container->count)
    >
    > This will work with all containers. Unless you use lcc-win and have
    > true generic functions (or use C++) the macro is the only really
    > portable solution.


    Judicious use of void* can let you use functions (inline or not),
    though at some loss of type checking. The following sample code,
    which expands on what Eric Sosman pointed, is a bit long; the GetCount
    function is the relevant part.

    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>

    typedef struct {
    size_t count;
    } AllContainersHaveThis;

    typedef struct {
    AllContainersHaveThis common;
    int One;
    } ContainerOne;

    typedef struct {
    AllContainersHaveThis common;
    char *Two;
    } ContainerTwo;

    typedef struct {
    AllContainersHaveThis common;
    double Three;
    } ContainerThree;

    ContainerOne *new1(size_t count, int One)
    {
    ContainerOne *const result = malloc(sizeof *result);
    if (result != NULL) {
    result->common.count = count;
    result->One = One;
    }
    return result;
    }

    ContainerTwo *new2(size_t count, char *Two)
    {
    ContainerTwo *const result = malloc(sizeof *result);
    if (result != NULL) {
    result->common.count = count;
    result->Two = Two;
    }
    return result;
    }

    ContainerThree *new3(size_t count, double Three)
    {
    ContainerThree *const result = malloc(sizeof *result);
    if (result != NULL) {
    result->common.count = count;
    result->Three = Three;
    }
    return result;
    }

    size_t GetCount(void *container)
    {
    const AllContainersHaveThis *common_ptr = container;
    return common_ptr->count;
    }

    int main(void)
    {
    ContainerOne *c1 = new1(10, 42);
    ContainerTwo *c2 = new2(20, "hello");
    ContainerThree *c3 = new3(30, 1.375);
    printf("GetCount(c1) = %zu\n", GetCount(c1));
    printf("GetCount(c2) = %zu\n", GetCount(c2));
    printf("GetCount(c3) = %zu\n", GetCount(c3));
    return 0;
    }

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, Jan 2, 2010
    #15
  16. Keith Thompson <> writes:
    > jacob navia <> writes:
    >> One situation where macros are the only solution, and inline functions
    >> just do not cut it is when you have several structures that share a
    >> common field, and you want to access it without a function call.
    >>
    >> For instance in a container library (strange, what a coincidence :) )
    >> all the containers share the "count" field, that access the number of
    >> elements in the container.
    >>
    >> Here it would be impossible to use an inline function since all the
    >> containers are different types. A macro is the only solution:
    >>
    >> #define GetCount(container) (container->count)
    >>
    >> This will work with all containers. Unless you use lcc-win and have
    >> true generic functions (or use C++) the macro is the only really
    >> portable solution.

    >
    > Judicious use of void* can let you use functions (inline or not),
    > though at some loss of type checking. The following sample code,
    > which expands on what Eric Sosman pointed, is a bit long; the GetCount
    > function is the relevant part.

    [snip]
    > size_t GetCount(void *container)
    > {
    > const AllContainersHaveThis *common_ptr = container;
    > return common_ptr->count;
    > }

    [snip]

    A major drawback of this approach is that the compiler won't
    complain about a call like
    GetCount("hello");
    (On my system it returned 1819043176, which is meaningful but not
    in any useful way.)

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, Jan 2, 2010
    #16
  17. jacob navia

    Flash Gordon Guest

    Eric Sosman wrote:
    > On 1/2/2010 1:57 PM, jacob navia wrote:
    >> Eric Sosman a écrit :
    >>> On 1/2/2010 12:39 PM, jacob navia wrote:
    >>>> Eric Sosman a écrit :
    >>>>>
    >>>>> typedef struct {
    >>>>> size_t count;
    >>>>> nobili_t baron;
    >>>>> royal_t duke;
    >>>>> } AllContainersHaveThis;
    >>>>> [...]
    >>>>
    >>>> Sure, but then the access is
    >>>> container->common.count;
    >>>> and not
    >>>> container->count;
    >>>> what is easier on the user.
    >>>
    >>> If you can do `container->count', why bother with
    >>> your `GetCount(container)' macro in the first place?
    >>> What problem are you trying to solve?
    >>>

    >>
    >> I would prefer not to let users use "->count" directly in case
    >> I need to change it later, because, for instance, capitalization
    >> problems, (Count or count?), or because it is better to call
    >> it NumberOfEelemnts, etc.


    If you might decide to change it's name, then might you not also decide
    to change GetCount to GetNumberOfElements? Or change its capitalization?
    The only solution to the problem of what to call things and possibly
    needing to rename them is to design everything sufficiently that the
    odds are the name will always be appropriate and not clash with anything
    else you might want to do.

    > If the users aren't supposed to access `count' directly,
    > why object that `container->count' is "easier on the user" than
    > `container->common.count'? Neither form will be used at all,
    > so why prefer one as "easier" than the other?
    >
    > I still don't get it ...
    >
    >> But not ALL members of the common subset have macros for them
    >> since I want to avoid using common names as much as possible.

    >
    > Sorry: I don't understand this at all. I imagine this is
    > because I lack a good deal of context, design and implementation
    > details that reside in your head but not in mine.


    It does seem odd to me. The one reason I can see you might want to do
    some things wrapped in a macro or inline function is if count *might* be
    a simple field or you *might* be calling a function which actually
    counts the elements, but in that case make it a function with the simple
    case just being a simple inline function.

    >> The GetCount macro is on by default, but if it collides with
    >> one name in your name space you should be able to disable it.

    >
    > And thus give up the ability to find out how many elements
    > a container holds? I still *really* don't get it ...


    Well, you could still access container->count ... ;-)
    The macros/functions should have an appropriate prefix to minimise the
    chances of a name clash. E.g. start everything with cnt (or Cnt) or
    whatever. After all, you might be using another library which has a
    GetCount function (which is, I think, Jacob's concern here).

    >> As you know, C has no "hidden/protected" structure members.

    >
    > No. It's all or nothing: Expose all of a struct's elements,
    > or make the whole struct an incomplete type and hide everything.
    > (For an abstract data type like "container," the latter seems
    > such a natural choice that I don't understand why you avoid it.)


    It would be nice if you could have a struct which contains an incomplete
    struct. Which, of course, would make it incomplete but still allow
    access to some things...

    struct container {
    size_t count;
    struct hidden hidden;
    }

    If this was added to C the container struct would obviously have most of
    the same restrictions as any other incomplete type, i.e. you could
    declare pointers to the type, not arrays or objects. You would need a
    special case rule that you could dereference it if and *only* if you
    then just accessed a member the definition of which you could see. Also
    the incomplete type would have to be at the end (just as with flexible
    array members).

    I suppose you could just do an array which was large enough for all the
    extra info you wanted then cast to/from the correct
    pointer-to-struct-type inside the library.
    --
    Flash Gordon
     
    Flash Gordon, Jan 3, 2010
    #17
    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. Nish
    Replies:
    4
    Views:
    505
    Thomas Stegen
    Oct 8, 2004
  2. TGOS
    Replies:
    3
    Views:
    383
    Kevin Bracey
    Feb 28, 2005
  3. Ajay
    Replies:
    5
    Views:
    400
    Pete Becker
    Apr 1, 2006
  4. Replies:
    7
    Views:
    452
  5. , India

    inline function vs function-like macro

    , India, Mar 6, 2007, in forum: C Programming
    Replies:
    2
    Views:
    646
    Flash Gordon
    Mar 6, 2007
Loading...

Share This Page