Defining an alias

Discussion in 'C Programming' started by jacob navia, Dec 19, 2009.

  1. jacob navia

    jacob navia Guest

    Sometimes you need to have two functions that have the same body.

    For instance, in my container library I have a function
    "Add" that will add an element at the end of the list,
    and another "Pop" that will take out the first element of the list.

    If you implement a queue as a list, the function "Enqueue" will be
    the same as "Add", and "Dequeue" the same as "Pop". The only
    way to do this in standardese is:

    int Enqueue(List *l, void *item)
    {
    return Add(l,item);
    }

    This is wasteful since the call overhead is payed for
    no reason.

    The syntax for doing that under lcc-win is:

    int __declspec(naked) SomeNewName(int a, int b) { }
    int SomeOtherName(int a,int b)
    {
    // Here we have the real body of the function
    }

    The first declaration specifies a "naked" function i.e. one which
    the compiler will treat as special and not generate any prologue
    nor epilogue to it, and will not complain about missing return
    values.

    The second declaration is the body of the function. The first one
    will be just an assembler label. It wilk take zero bytes of space.

    "Naked" functions are supposed to be assembly language ones, by the way.

    All this syntax is quite horrible. I am conforted however, because gcc
    has an even uglier syntax:

    http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Function-Attributes.html:

    The alias attribute causes the declaration to be emitted as an alias for another symbol, which must
    be specified. For instance,

    void __f () { /* Do something. */; }
    void f () __attribute__ ((weak, alias ("__f")));


    defines `f' to be a weak alias for `__f'. It is an error if `__f' is not defined in the same
    translation unit.

    It is not clear what "weak" means in this context, and I am not sure that
    gcc does the same thing as lcc-win...

    Any ideas? Which syntax would be better?

    Thanks
     
    jacob navia, Dec 19, 2009
    #1
    1. Advertising

  2. jacob navia

    Alan Curry Guest

    In article <hgh6b7$cbt$>, jacob navia <> wrote:
    >Sometimes you need to have two functions that have the same body.
    >
    >For instance, in my container library I have a function
    >"Add" that will add an element at the end of the list,
    >and another "Pop" that will take out the first element of the list.
    >
    >If you implement a queue as a list, the function "Enqueue" will be
    >the same as "Add", and "Dequeue" the same as "Pop". The only
    >way to do this in standardese is:
    >
    >int Enqueue(List *l, void *item)
    >{
    > return Add(l,item);
    >}
    >
    >This is wasteful since the call overhead is payed for
    >no reason.


    Some people would just make it static inline in the header file, then there's
    no overhead (if the compiler does inlines at all).

    >
    >The syntax for doing that under lcc-win is:
    >
    >int __declspec(naked) SomeNewName(int a, int b) { }
    >int SomeOtherName(int a,int b)
    >{
    > // Here we have the real body of the function
    >}


    I see nothing that actually specifies where SomeNewName's "real body" is to
    be found. Does it just take the next one in the source file? Adjacency in the
    source code seems like a flimsy thing to rely on.

    >http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Function-Attributes.html:
    >
    >The alias attribute causes the declaration to be emitted as an alias for
    >another symbol, which must
    >be specified. For instance,
    >
    > void __f () { /* Do something. */; }
    > void f () __attribute__ ((weak, alias ("__f")));
    >
    >
    >defines `f' to be a weak alias for `__f'. It is an error if `__f' is not
    >defined in the same
    >translation unit.


    weak symbols are used in libraries (libc especially) to provide a function
    that is available in the user's namespace, but will get out of the way if he
    provides his own definition. So you can call a non-stdc function like fork()
    and the linker will find the one in libc, or you can have your own global
    variable called fork in a plain C program and the linker won't complain about
    the conflict, since the one in libc is weak.

    The double-underscore version of the function is there because the
    implementation of standard C functions needs to call the non-stdc functions
    sometimes. system() must call fork(), so it uses __fork() to avoid a conflict
    in a program that makes use of system() but also has an unrelated global
    variable or function named "fork". fopen() must call open(), so it calls
    __open() which is a weak alias for open(), etc.

    >
    >It is not clear what "weak" means in this context, and I am not sure that
    >gcc does the same thing as lcc-win...


    The gcc syntax actually tells you that the 2 names are related, by having the
    alias "__f" attribute attached to the declaration of f. They don't need to be
    one right after the other in a specific order, like your "naked" thing does.

    --
    Alan Curry
     
    Alan Curry, Dec 19, 2009
    #2
    1. Advertising

  3. jacob navia

    Seebs Guest

    On 2009-12-19, jacob navia <> wrote:
    > It is not clear what "weak" means in this context, and I am not sure that
    > gcc does the same thing as lcc-win...


    "weak" is a traditional thing in linkers at least on the recent unixy systems
    I've used. A weak reference is a reference which exists if needed but not
    found, but which never clashes with anything.

    So, as an example: Some BSDish systems used to declare a symbol "end" which
    referred to the end of the program's space, roughly. That could be a problem
    if you defined a symbol named "end" and tried to call it or use it. So!
    Solution is, make it a weak reference. If you refer to end and link without
    providing anything named end, you pick that one up. If you provide your own,
    yours wins.

    This is often used to handle things where a given function name is in the
    user's namespace but is traditional. For instance, in standard C, the user
    is permitted to define a function named "open". In unix-land, open is a
    standard system call, which is usually (but not always) accessed through a
    C wrapper. The gcc approach would be that the library would provide a
    symbol named something like __open or __syscall_open, and then a "weak
    alias" under the name open.

    > Any ideas? Which syntax would be better?


    The gcc syntax is more flexible, because it can be used to refer to things
    that aren't defined anywhere near you. You can have many references to a
    single thing, and the "weak" reference allows you to ensure that you are
    more resilient in the face of possible namespace clashes.

    -s
    --
    Copyright 2009, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
     
    Seebs, Dec 19, 2009
    #3
  4. jacob navia

    Ian Collins Guest

    jacob navia wrote:
    > Sometimes you need to have two functions that have the same body.
    >
    > For instance, in my container library I have a function
    > "Add" that will add an element at the end of the list,
    > and another "Pop" that will take out the first element of the list.
    >
    > If you implement a queue as a list, the function "Enqueue" will be
    > the same as "Add", and "Dequeue" the same as "Pop". The only
    > way to do this in standardese is:
    >
    > int Enqueue(List *l, void *item)
    > {
    > return Add(l,item);
    > }
    >
    > This is wasteful since the call overhead is payed for
    > no reason.


    But surely most, if not all, compiler will inline such a trivial function?

    <snip>

    > All this syntax is quite horrible. I am conforted however, because gcc
    > has an even uglier syntax:
    >
    > http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Function-Attributes.html:
    >
    > The alias attribute causes the declaration to be emitted as an alias for
    > another symbol, which must be specified. For instance,
    >
    > void __f () { /* Do something. */; }
    > void f () __attribute__ ((weak, alias ("__f")));
    >
    >
    > defines `f' to be a weak alias for `__f'. It is an error if `__f' is not
    > defined in the same
    > translation unit.
    >
    > It is not clear what "weak" means in this context, and I am not sure that
    > gcc does the same thing as lcc-win...


    The usual meaning (at least in Unix land) is described here:
    http://en.wikipedia.org/wiki/Weak_symbol

    The example above appears to be an extension of the weak symbol concept.

    > Any ideas? Which syntax would be better?


    Let the compiler inline the call.

    --
    Ian Collins
     
    Ian Collins, Dec 19, 2009
    #4
  5. jacob navia

    Stefan Ram Guest

    jacob navia <> writes:
    >the same as "Add", and "Dequeue" the same as "Pop". The only
    >way to do this in standardese is:
    >int Enqueue(List *l, void *item)
    >{
    > return Add(l,item);
    >}


    Why not

    int (*Enqueue)(List *l, void *item) = Add;

    ?
     
    Stefan Ram, Dec 19, 2009
    #5
  6. jacob navia

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >int (*Enqueue)(List *l, void *item) = Add;


    Rereading this, I would like to add a »const«:

    int (*const Enqueue)(List *l, void *item) = Add;
     
    Stefan Ram, Dec 19, 2009
    #6
  7. On 12/18/09 5:01 PM, Ian Collins wrote:
    > But surely most, if not all, compiler will inline such a trivial function?
    > Let the compiler inline the call.


    Seconded. If that wasn't working, I'd probably use the function pointer
    solution.

    -Beej
     
    Beej Jorgensen, Dec 19, 2009
    #7
  8. jacob navia

    jacob navia Guest

    jacob navia a écrit :


    (snip)

    Thanks for the answers guys. Yes, the "static inline" syntax is better.

    I think that the container library will require C99 then, and leave
    Microsoft compilers out... They have inline, but I do not remember if
    they accept it in C mode.

    jacob
     
    jacob navia, Dec 19, 2009
    #8
  9. jacob navia <> writes:
    > jacob navia a écrit :
    > (snip)
    >
    > Thanks for the answers guys. Yes, the "static inline" syntax is better.
    >
    > I think that the container library will require C99 then, and leave
    > Microsoft compilers out... They have inline, but I do not remember if
    > they accept it in C mode.


    What's wrong with the const function pointer solution?

    --
    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, Dec 19, 2009
    #9
  10. jacob navia

    Seebs Guest

    Seebs, Dec 19, 2009
    #10
  11. Ian Collins writes:
    > But surely most, if not all, compiler will inline such a trivial
    > function?


    gcc doesn't by default, even if it is declared inline.

    Only gcc -O (optimizing) inlines functions declared 'inline',
    and also other small functions called just once. At level -O3
    it'll inline small functions called more than once.

    --
    Hallvard
     
    Hallvard B Furuseth, Dec 19, 2009
    #11
  12. jacob navia

    Ian Collins Guest

    Hallvard B Furuseth wrote:
    > Ian Collins writes:
    >> But surely most, if not all, compiler will inline such a trivial
    >> function?

    >
    > gcc doesn't by default, even if it is declared inline.
    >
    > Only gcc -O (optimizing) inlines functions declared 'inline',
    > and also other small functions called just once. At level -O3
    > it'll inline small functions called more than once.


    How often do you deploy application built without any optimisation?

    --
    Ian Collins
     
    Ian Collins, Dec 19, 2009
    #12
  13. On 19 Dec 2009 at 9:46, jacob navia wrote:
    > I think that the container library will require C99 then, and leave
    > Microsoft compilers out...


    You'll also excluded Heathfield's version of gcc from the last century!
     
    Antoninus Twink, Dec 20, 2009
    #13
  14. jacob navia

    Stefan Ram Guest

    -berlin.de (Stefan Ram) writes:
    >int (*const Enqueue)(List *l, void *item) = Add;


    gcc seems to be willing to replace the call to »enqueue«
    with a call to »add« when it is compiling »main«:

    #include <stdlib.h>
    inline int add( void ){ return 7; }
    int( * const enqueue )( void )= add;
    int main( void ){ exit( enqueue() ); }

    gcc -O3 -S -std=c99 -finline-functions-called-once test.c

    main:
    ...
    call add
    movl %eax, (%esp)
    call exit
    ...

    So it acknowledges that »enqueue« will always be »add«.
    While without the »const«, it will call »enqueue«.

    main:
    ...
    call *enqueue
    movl %eax, (%esp)
    call exit
    ...

    Thus, there is no reason visible that forbids gcc to inline
    the call in the first case - it just does not do it,
    but then this is a property of a special implementation,
    not necessarily of all implementations of the programming
    language C.
     
    Stefan Ram, Dec 20, 2009
    #14
  15. -berlin.de (Stefan Ram) writes:

    > -berlin.de (Stefan Ram) writes:
    >>int (*const Enqueue)(List *l, void *item) = Add;

    >
    > gcc seems to be willing to replace the call to »enqueue«
    > with a call to »add« when it is compiling »main«:
    >
    > #include <stdlib.h>
    > inline int add( void ){ return 7; }
    > int( * const enqueue )( void )= add;
    > int main( void ){ exit( enqueue() ); }

    <snip>
    > So it acknowledges that »enqueue« will always be »add«.
    > While without the »const«, it will call »enqueue«.

    <snip>
    > Thus, there is no reason visible that forbids gcc to inline
    > the call in the first case - it just does not do it,


    My gcc does. It seems there is no reason not to use this alias method
    is the compiler can even inline the pointed-to function.

    <snip>
    --
    Ben.
     
    Ben Bacarisse, Dec 20, 2009
    #15
  16. jacob navia

    Fred Guest

    On Dec 20, 5:09 am, Ben Bacarisse <> wrote:
    > -berlin.de (Stefan Ram) writes:
    > > -berlin.de (Stefan Ram) writes:
    > >>int (*const Enqueue)(List *l, void *item) = Add;

    >
    > >   gcc seems to be willing to replace the call to »enqueue«
    > >   with a call to »add« when it is compiling »main«:

    >
    > > #include <stdlib.h>
    > > inline int add( void ){ return 7; }
    > > int( * const enqueue )( void )= add;
    > > int main( void ){ exit( enqueue() ); }

    > <snip>
    > >   So it acknowledges that »enqueue« will always be »add«.
    > >   While without the »const«, it will call »enqueue«.

    > <snip>
    > >   Thus, there is no reason visible that forbids gcc to inline
    > >   the call in the first case - it just does not do it,

    >
    > My gcc does.  It seems there is no reason not to use this alias method
    > is the compiler can even inline the pointed-to function.
    >
    > - Show quoted text -


    I don't get it. If the two functions are truly identical, why not do
    this
    (this thread has been inconsistent in capitalization of the function
    names):

    #define Enqueue Add

    --
    Fred K
     
    Fred, Dec 21, 2009
    #16
  17. jacob navia

    bartc Guest

    Stefan Ram wrote:
    > jacob navia <> writes:
    >> the same as "Add", and "Dequeue" the same as "Pop". The only
    >> way to do this in standardese is:
    >> int Enqueue(List *l, void *item)
    >> {
    >> return Add(l,item);
    >> }

    >
    > Why not
    >
    > int (*Enqueue)(List *l, void *item) = Add;


    Or:

    int Enqueue(List *l, void *item) = Add;

    (which of course is a new syntax, but does away with the extra obfuscating
    indirection layer.)

    Or I might just use (and I don't care myself about new keywords):

    alias Enqueue = Add;

    which saves repeating (and having to maintain) the function signature.

    (I quite like Fred's macro solution too, if there's no catch.)

    All these methods however suggest some hierarchy between Enqueue and Add,
    whereas they should be both be at the same level. Perhaps then define both
    in terms of a dummy third routine:

    int Enqueue_or_Add(List *l, void *item) {...}

    alias Enqueue = Enqueue_or_Add;
    alias Add = Enqueue_or_Add;

    --
    Bartc
     
    bartc, Dec 22, 2009
    #17
  18. Fred <> writes:
    <snip>
    >> > -berlin.de (Stefan Ram) writes:
    >> >>int (*const Enqueue)(List *l, void *item) = Add;

    <snip>
    > I don't get it. If the two functions are truly identical, why not do
    > this
    > (this thread has been inconsistent in capitalization of the function
    > names):
    >
    > #define Enqueue Add


    A lot of people have grown wary of macro-based solutions simply
    because the mechanism is so crude. Using the above will be fine in
    the vast majority of cases but you'll be tripped up if you try to use
    a macro to replace Enqueue with my_debug_Enqueue and you might be
    puzzled that the debugger shows that you no longer have a struct
    Enqueue (badly named, I agree, but that is not really the point).

    --
    Ben.
     
    Ben Bacarisse, Dec 22, 2009
    #18
  19. Ian Collins writes:
    >Hallvard B Furuseth wrote:
    >>Ian Collins writes:
    >>> But surely most, if not all, compiler will inline such a trivial
    >>> function?

    >>
    >> gcc doesn't by default, even if it is declared inline.
    >>
    >> Only gcc -O (optimizing) inlines functions declared 'inline',
    >> and also other small functions called just once. At level -O3
    >> it'll inline small functions called more than once.

    >
    > How often do you deploy application built without any optimisation?


    Don't know, I don't compile most of the programs I run. I do hear from
    people who say they don't use gcc's optimization because it is broken.
    (My guess is their application is broken, but what do I know...)

    In any case, gcc -O2 is a common optimization level - and like I just
    said, that's not enough if the function was not declared inline.

    --
    Hallvard
     
    Hallvard B Furuseth, Dec 22, 2009
    #19
  20. Gareth Owen writes:
    > Hallvard B Furuseth <> writes:
    >> Ian Collins writes:
    >>> But surely most, if not all, compiler will inline such a trivial
    >>> function?

    >>
    >> gcc doesn't by default, even if it is declared inline.
    >>
    >> Only gcc -O (optimizing) inlines functions declared 'inline', and also
    >> other small functions called just once. At level -O3 it'll inline
    >> small functions called more than once.

    >
    > But if you're not compiling with any optimization, you don't care about
    > the performance hit of the extra function setup, so its a moot point.


    I do in fact care about producing reasonable default behavior, so I try
    to avoid active pessimizations. Though in this case and optimzation is
    likely not the main point, code bloat is. (Lots of compiled small
    unused functions which could have been removed.)

    --
    Hallvard
     
    Hallvard B Furuseth, Dec 22, 2009
    #20
    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. Khashishi
    Replies:
    3
    Views:
    5,795
    Weng Tianxiang
    Sep 22, 2004
  2. =?ISO-8859-15?Q?Stefan_Schw=E4rzler?=

    what's incorrect ALIAS

    =?ISO-8859-15?Q?Stefan_Schw=E4rzler?=, Aug 3, 2005, in forum: VHDL
    Replies:
    1
    Views:
    479
    Jonathan Bromley
    Aug 4, 2005
  3. TigerJade
    Replies:
    4
    Views:
    518
    Jonathan Bromley
    Aug 5, 2005
  4. johny smith
    Replies:
    8
    Views:
    451
    Peter Koch Larsen
    Jul 2, 2004
  5. grocery_stocker
    Replies:
    9
    Views:
    824
    grocery_stocker
    May 24, 2008
Loading...

Share This Page