gonetwork-programminglow-level-io

Endianness checking in go runtime for linux


There is this fragment of the function anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) residing in syscall_linux.go file in syscall package in the go runtime:

    case AF_INET:
    pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
    sa := new(SockaddrInet4)
    p := (*[2]byte)(unsafe.Pointer(&pp.Port))
    sa.Port = int(p[0])<<8 + int(p[1])
    sa.Addr = pp.Addr
    return sa, nil

What can be seen here is the port number gets converted from network byte order (big endian) to host byte order (little endian). But doesn't the endianness depend on the architecture? Will this code have correct behavior on linux for ppc64 for example (which is big endian)? Why there are no either checking for this nor different versions for different architectures?


Solution

  • You just have small glitch in your reasoning ;-) When you manipulate a value of an integer type using a programming language (and even assembler / machine code), there simply is no concept of endianness in play—only the ordering of bits: from the least significant one to the most. The actual way these bits are stored is completely irrelevant.

    When you do

    int(p[0])<<8
    

    you shift the whole value of type int 8 bits towards the most significant bit — making 8 zero bits appear as the least significant ones, and the 8 most significant bits drop off and get lost. The way we name this thing — "shift left", — and the way we have it in the Go's (and C's etc) syntax — <<, — stems from the fact the education of most of us is affected by "western" tradition, in which we write numbers in the way that their least significant digit is always the rightmost one, and this affected the syntax of the programming languages we've designed. So, basically, we "shift left" because we write numbers (on paper) — including in binary form — in the way their LSB is always the rightmost, and their MSB is always the leftmost, so shifting the bits to the left is shifting them from the least significant ones to the most significant ones; what matters is this fact, not which end of an integer value has a lower address in memory (if any, as, say, CPU registers on today's CPUs do not have addresses).

    To recap, the process of bitwise operations has no direct relation to how a particular H/W architecture stores the numbers in CPU registers and in memory.