My TL;DR take on this: that htons() both takes and returns a 16 bit integer is hazardous
I'd agree that if you exposed integers that had been given the htons() treatment far and wide in your code, that could lead to trouble. Would lead to trouble.
However .. in practice I've virtually never seen htons, htonl used anywhere but in close proximity to stuffing a sockaddr prior to a bind/connect/sendto etc, i.e., in relation to classic BSD socket calls. That you're forced to overtly stuff structs (and deal with low-level crufties like endieness) to feed to the API seems like an API design issue.
These functions return the same type as their argument for simplicity and practicality but the only actual use is to convert between wire/byte stream format and internal representation. It's not a problem.
Way back, {hton,ntoh}{s,l,ll} didn't originally use C99 types because they predated stdint. Instead, macros and platform specific-isms were used to choose the right types.
As more primitive functions, swap_endian_u{16,32,64,128} are useful to build {hton,ntoh}{s,l,ll}.
IEN-137 is wrong and presented it as a false case of bikeshedding. Standardizing network order on little rather than big endian would save energy. There's no sense to swapping just to swap it back in most cases. That's double work for no reason except intellectual purity. Billions of devices doing a tiny bit of extra work adds up.
depending on the device and instruction set the swap is entirely free, e.g. where it's just a choice of a different load instructions (or the cool arches where you just make an unaligned read, the lsb triggers swapping).
If energy is your concern making arches more energy efficient for swapping is the sensible thing as there are already many protocols and file formats in network order. There is fundamentally no reason for it to have a energy cost at all.
And if you're really concerned about energy, the energy needed to communicate and store bits usually vastly dominates the energy needed to compute on them. On that basis protocols should be using varrious tightly packed / variable length encodings instead.
I don’t see what makes htons special here. The C standard library is full of functions that return an int that isn’t an integer.
For example, printf returns “a nonnegative integer or an error code”, creat returns a file descriptor, mknod returns a Boolean (coded as 0=true, -1=false) and sets errno, but all have return type int.
Strong typing historically wasn’t a goal at all in C. K&R C and its predecessors liked everything to be an int, where possible. For example, if your code called a function foo, the compiler assumed it would be able to find it at link time and return an integer (the ‘implicit int rule’)
“Every C program coded to run in a hosted execution environment contains the definition (not the prototype) of a function named main, which is the designated start of the program.
int main (void) { body } (1)
int main (int argc, char *argv[]) { body } (2)
/* another implementation-defined signature */ (since C99.) (3)
”
(C++ is a bit more strict. There, main must return an int)
The author is definitely wrong about one thing (probably several, but who's counting):
"There is actually a relatively easy fix: if we insist on reading numbers with the most significant digit on the right (which we do), and the computer insists on storing less significant components first (which it does), these two desires can be reconciled by printing the hex dump from right to left"
Nope, that won't work. The reason is that you don't know whether the items in the hex dump are bytes, words, dwords, qwords, etc.
If your hex dump was all 32 bit words, it would kinda work, but the addresses would be "swizzled" (03 02 01 00 07 06 05 04, etc. guh!)
But what about hexdump("hello world!") which would become
lleh ow o !dlr
There's really no fix. Hex dumps on a byte oriented computer must be oriented in a consistent way wrt. address. The only think I can think of is some kind of hover or alternate view if you highlight a series of bytes.
14 comments
[ 0.22 ms ] story [ 45.9 ms ] threadI'd agree that if you exposed integers that had been given the htons() treatment far and wide in your code, that could lead to trouble. Would lead to trouble.
However .. in practice I've virtually never seen htons, htonl used anywhere but in close proximity to stuffing a sockaddr prior to a bind/connect/sendto etc, i.e., in relation to classic BSD socket calls. That you're forced to overtly stuff structs (and deal with low-level crufties like endieness) to feed to the API seems like an API design issue.
As more primitive functions, swap_endian_u{16,32,64,128} are useful to build {hton,ntoh}{s,l,ll}.
IEN-137 is wrong and presented it as a false case of bikeshedding. Standardizing network order on little rather than big endian would save energy. There's no sense to swapping just to swap it back in most cases. That's double work for no reason except intellectual purity. Billions of devices doing a tiny bit of extra work adds up.
If energy is your concern making arches more energy efficient for swapping is the sensible thing as there are already many protocols and file formats in network order. There is fundamentally no reason for it to have a energy cost at all.
And if you're really concerned about energy, the energy needed to communicate and store bits usually vastly dominates the energy needed to compute on them. On that basis protocols should be using varrious tightly packed / variable length encodings instead.
For example, printf returns “a nonnegative integer or an error code”, creat returns a file descriptor, mknod returns a Boolean (coded as 0=true, -1=false) and sets errno, but all have return type int.
Strong typing historically wasn’t a goal at all in C. K&R C and its predecessors liked everything to be an int, where possible. For example, if your code called a function foo, the compiler assumed it would be able to find it at link time and return an integer (the ‘implicit int rule’)
https://en.cppreference.com/w/c/language/main_function:
“Every C program coded to run in a hosted execution environment contains the definition (not the prototype) of a function named main, which is the designated start of the program.
”(C++ is a bit more strict. There, main must return an int)
To the type system, they look the same. There are ways to structure your code so that your program (almost always) does the right thing.
Or, add more semantically meaningful types and have your language and libraries help you do the right thing. I like it.
If your hex dump was all 32 bit words, it would kinda work, but the addresses would be "swizzled" (03 02 01 00 07 06 05 04, etc. guh!)
But what about hexdump("hello world!") which would become
There's really no fix. Hex dumps on a byte oriented computer must be oriented in a consistent way wrt. address. The only think I can think of is some kind of hover or alternate view if you highlight a series of bytes.