views:

1838

answers:

4
extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
 __THROW;

I found the above function definition in /usr/include/netinet/ether.h on a Linux box.

Can someone explain what the double underscores mean in front of const (keyword), addr (identifier) and at last __THROW.

A: 

By convention in some libraries, this indicates that a particular symbol is for internal use and not intended to be part of the public API of the library.

Rob H
@Rob..So does that mean for programming purposes i can consider the function definitionextern int ether_hostton (__const char *__hostname, struct ether_addr *__addr) __THROW;to be without underscores and __THROW.?
Deepak Konidena
Maybe those are macros, and are for C++ compatibility? If you are compiling in C++ mode, `__THROW` == `throw()` and if const is supported then `__const` == `const`, or something along that?
Johannes Schaub - litb
@Deepak: I don't understand your question.
Rob H
@Rob if they are intended for internal use, could i ignore the underscores and just define variables of the desired type and access the values during function calls.I just wanted to know if the underscore made any difference to the programmer who is using the API.
Deepak Konidena
@Deepak: as far as you are concerned, the function returns an `int` and takes a string (`char *`) and a `struct ether_addr` pointer. It doesn't matter what sort of string you pass as the name - the function won't modify it. That's all you really need to know. If you were writing the function, you'd have to worry about the semantics of `__const`. The `__THROW` bit is meaningless in C unless there is either `#define __THROW /* Nothing */` or a compiler-specific extension is used; you don't have to worry about it, therefore.
Jonathan Leffler
@Jonathan..Thanks a million. That clarifies some concepts.
Deepak Konidena
+1  A: 

The underscore in __const means that this keyword is a compiler extension and using it is not portable (The const keyword was added to C in a later revision, 89 I think). The __THROW is also some kind of extension, I assume that it gets defined to some __attribute__(something) if gcc is used, But I'm not sure on that and too lazy to check. The __addr can mean anything the programmer wanted it to mean, It's just a name.

Caotic
So, from a user's perspective..if i just defined char *hostnameval, i could access the __const char* __hostname value?
Deepak Konidena
Ok, I don't think I understand what you want to ask in that comment. The \__conts tells you, just like const, that the function will not change the value of \__hostname. For calling that function, the name \__hostname makes no difference to hostname or any other possible name.
Caotic
@Caotic...i meantif ether_hostton (__const char *__hostname, struct ether_addr *__addr) is just as good as ether_hostton (const char *(hostname/anyname), struct ether_addr *addr) as far as a user is c oncerned ?
Deepak Konidena
Yes, there should be no differences
Caotic
+15  A: 

Names with double leading underscores are reserved for use by the implementation. This does not necessarily mean they are internal per se, although they often are.

The idea is, you're not allowed to to use any names starting with __, so the implementation is free to use them in places like macro expansions, or in the names of syntax extensions (e.g. __gcnew is not part of C++, but Microsoft can add it to C++/CLI confident that no existing code should have something like int __gcnew; in it that would stop compiling).

To find out what these specific extensions mean, i.e. __const you'll need to consult the documentation for your specific compiler/platform. In this particular case, you should probably consider the prototype in the documentation (e.g. http://www.kernel.org/doc/man-pages/online/pages/man3/ether%5Faton.3.html) to be the function's interface and ignore the __const and __THROW decorations that appear in the actual header.

Logan Capaldo
Thanks for the link..that definitely helps.
Deepak Konidena
+11  A: 

In C, symbols starting with an underscore followed by either an upper-case letter or another underscore are reserved for the implementation. You as a user of C should not create any symbols that start with the reserved sequences. In C++, the restriction is more stringent; you the user may not create a symbol containing a double-underscore.

Given:

extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;

The __const notation is there to allow for the possibility (somewhat unlikely) that a compiler that this code is used with supports prototype notations but does not have a correct understanding of the C89 standard keyword const. The autoconf macros can still check whether the compiler has working support for const; this code could be used with a broken compiler that does not have that support.

The use of __hostname and __addr is a protection measure for you, the user of the header. If you compile with GCC and the -Wshadow option, the compiler will warn you when any local variables shadow a global variable. If the function used just hostname instead of __hostname, and if you had a function called hostname(), there'd be a shadowing. By using names reserved to the implementation, there is no conflict with your legitimate code.

The use of __THROW means that the code can, under some circumstances, be declared with some sort of 'throw specification'. This is not standard C; it is more like C++. But the code can be used with a C compiler as long as one of the headers (or the compiler itself) defines __THROW to empty, or to some compiler-specific extension of the standard C syntax.


Section 7.1.3 of the C standard (ISO 9899:1999) says:

7.1.3 Reserved identifiers

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

— All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

— Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).

— All identifiers with external linkage in any of the following subclauses (including the future library directions) are always reserved for use as identifiers with external linkage.154)

— Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

If the program removes (with #undef) any macro definition of an identifier in the first group listed above, the behavior is undefined.

Footnote 154) The list of reserved identifiers with external linkage includes errno, math_errhandling, setjmp, and va_end.


See also What are the rules about using an underscore in a C++ identifier; a lot of the same rules apply to both C and C++, though the embedded double-underscore rule is in C++ only, as mentioned at the top of this answer.

Jonathan Leffler