Void-safety (and related things)

bearophile bearophileHUGS at lycos.com
Fri Aug 21 09:58:48 PDT 2009


Joel C. Salomon:

>http://plan9.bell-labs.com/sys/doc/comp.html<

Thank you for that link.
I can see some interesting things in that very C-like language:

>The #if directive was omitted because it greatly complicates the preprocessor, is never necessary, and is usually abused. Conditional compilation in general makes code hard to understand; the Plan 9 source uses it sparingly. Also, because the compilers remove dead code, regular if statements with constant conditions are more readable equivalents to many #ifs.<

Can the "static if" be removed from D then?

------------------

Variables inside functions can have any order, are D compilers too doing this?

>Unlike its counterpart on other systems, the Plan 9 loader rearranges data to optimize access. This means the order of variables in the loaded program is unrelated to its order in the source. Most programs don’t care, but some assume that, for example, the variables declared by
int a;
int b;
will appear at adjacent addresses in memory. On Plan 9, they won’t.<


------------------

Plan 9 uses this strategy to solve endianess-induced troubles in integer I/O:

>Plan 9 is a heterogeneous environment, so programs must expect that external files will be written by programs on machines of different architectures. The compilers, for instance, must handle without confusion object files written by other machines. The traditional approach to this problem is to pepper the source with #ifdefs to turn byte-swapping on and off. Plan 9 takes a different approach: of the handful of machine-dependent #ifdefs in all the source, almost all are deep in the libraries. Instead programs read and write files in a defined format, either (for low volume applications) as formatted text, or (for high volume applications) as binary in a known byte order. If the external data were written with the most significant byte first, the following code reads a 4-byte integer correctly regardless of the architecture of the executing machine (assuming an unsigned long holds 4 bytes):

ulong getlong(void) {
    ulong l;
    l = (getchar()&0xFF)<<24;
    l |= (getchar()&0xFF)<<16;
    l |= (getchar()&0xFF)<<8;
    l |= (getchar()&0xFF)<<0;
    return l;
}

Note that this code does not ‘swap’ the bytes; instead it just reads them in the correct order. Variations of this code will handle any binary format and also avoid problems involving how structures are padded, how words are aligned, and other impediments to portability. Be aware, though, that extra care is needed to handle floating point data.<

------------------

I don't fully understand this:

>the declaration
extern register reg;
(this appearance of the register keyword is not ignored) allocates a global register to hold the variable reg. External registers must be used carefully: they need to be declared in all source files and libraries in the program to guarantee the register is not allocated temporarily for other purposes. Especially on machines with few registers, such as the i386, it is easy to link accidentally with code that has already usurped the global registers and there is no diagnostic when this happens. Used wisely, though, external registers are powerful. The Plan 9 operating system uses them to access per-process and per-machine data structures on a multiprocessor. The storage class they provide is hard to create in other ways.<

Bye,
bearophile



More information about the Digitalmars-d mailing list