jmtd → software → endian
Problem: You have code which needs to deal with endian issues. E.g., you might need to byte-swap only on big or little-endian.
Practical example: integers in doom WAD files are little-endian, so you would conditionally byte-swap on big-endian machines.
How would you do it?
Approaches
Conditionals via C pre-processor
a GNU automake/configure/etc. script can give you a CPP define for the endianness. You can then conditionally #ifdef the code.
Problem: You break the endian-specific code, somehow, but never notice because your local architecture means it's not used on your architecture.
conditionals via C-level logic
How about defining the endian-checking logic in the C itself? That way the endian code is always compiled, so if you break it in a way which can be determined at compile-time you find out even if your local platform is not going to use that code.
#include <stdio.h>
int main() {
int i = 1;
int *p = &i;
if(1 == *(char*)p) printf("little-endian\n");
else printf("big-endian\n");
return 0;
}
The disadvantage here would be that you may have your binary full of redundant code.
However, the test is a constant expression, so a compiler should throw away the redundant branch. To find out if this happens, I conducted a small experiment.
Results
GCC
Using GCC's -O flag, setting 0, the redundant branch is present in the output. x86 assembly excerpts:
...
.LC0:
.string "little-endian\n"
.LC1:
.string "big-endian\n"
...
movl $.LC0, (%esp)
call printf
jmp .L3
.L2:
movl $.LC1, (%esp)
call printf
.L3:
...
Using the first level of optimisation, -O1, and the redundant branch is gone:
...
.LC0:
.string "little-endian"
...
andl $-16, %esp
movl $.LC0, (%esp)
call puts
...
These tests used GCC version 3.2.2.
Sun's CC on SPARC
Sun's C compiler does not throw away the redundant branch at any optimizer level. I am using "WorkShop Compilers 5.0 98/12/15 C 5.0".
The non-conditional approach
Missing from this article at the moment...