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

Defining an alias

1 view
Skip to first unread message

jacob navia

unread,
Dec 18, 2009, 7:22:49 PM12/18/09
to
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

Alan Curry

unread,
Dec 18, 2009, 7:56:51 PM12/18/09
to
In article <hgh6b7$cbt$1...@aioe.org>, jacob navia <j...@nospam.org> 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

Seebs

unread,
Dec 18, 2009, 7:58:33 PM12/18/09
to
On 2009-12-19, jacob navia <ja...@nospam.org> 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 / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Ian Collins

unread,
Dec 18, 2009, 8:01:45 PM12/18/09
to
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

Message has been deleted
Message has been deleted

Gareth Owen

unread,
Dec 19, 2009, 2:17:59 AM12/19/09
to
jacob navia <ja...@nospam.org> writes:

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

...

> Any ideas? Which syntax would be better?

static inline => const function pointer => macros

Unless you're Tom St Denis, in which case

macro => static inline => const function pointer

Beej Jorgensen

unread,
Dec 19, 2009, 2:52:05 AM12/19/09
to
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

jacob navia

unread,
Dec 19, 2009, 4:46:26 AM12/19/09
to
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

Keith Thompson

unread,
Dec 19, 2009, 11:43:32 AM12/19/09
to
jacob navia <ja...@spamsink.net> writes:
> jacob navia a écrit :

What's wrong with the const function pointer solution?

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

Seebs

unread,
Dec 19, 2009, 1:04:13 PM12/19/09
to
On 2009-12-19, Keith Thompson <ks...@mib.org> wrote:
> What's wrong with the const function pointer solution?

Can't be inlined.

Hallvard B Furuseth

unread,
Dec 19, 2009, 5:54:10 PM12/19/09
to
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

Ian Collins

unread,
Dec 19, 2009, 6:00:49 PM12/19/09
to

How often do you deploy application built without any optimisation?

--
Ian Collins

Gareth Owen

unread,
Dec 20, 2009, 3:42:54 AM12/20/09
to

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.

Antoninus Twink

unread,
Dec 20, 2009, 5:42:47 AM12/20/09
to
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!

Message has been deleted

Ben Bacarisse

unread,
Dec 20, 2009, 8:09:55 AM12/20/09
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> r...@zedat.fu-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.

Fred

unread,
Dec 21, 2009, 10:42:32 AM12/21/09
to
> - 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

bartc

unread,
Dec 21, 2009, 7:58:23 PM12/21/09
to
Stefan Ram wrote:

> jacob navia <ja...@nospam.org> 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


Ben Bacarisse

unread,
Dec 22, 2009, 7:51:28 AM12/22/09
to
Fred <fred.l.kl...@boeing.com> writes:
<snip>

>> > r...@zedat.fu-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.

Hallvard B Furuseth

unread,
Dec 22, 2009, 1:20:41 PM12/22/09
to

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

unread,
Dec 22, 2009, 1:23:37 PM12/22/09
to

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

Ian Collins

unread,
Dec 22, 2009, 1:51:08 PM12/22/09
to

Which can be taken care of by link time garbage collection!

--
Ian Collins

Richard Bos

unread,
Jan 13, 2010, 4:37:43 PM1/13/10
to
jacob navia <ja...@nospam.org> 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.

I may be missing something obvious here, but... what's wrong with

#define Enqueue Add

or even

#define Enqueue(l, i) Add((l), (i))

Richard

0 new messages