[comp.lang.c] making pointers from integers

torek@elf.ee.lbl.gov (Chris Torek) (03/29/91)

In article <1991Mar28.190320.10724@cbnewsj.att.com> asd@cbnewsj.att.com
(Adam S. Denton) writes:
>... consider the following code, which is ubiquitous
>in MSDOS: (my apologies for including platform-specific code here)
>
>   void far *p;
>   ...
>   p = (void far *) 0xFFFFE000;
>
>when IMHO the proper abstraction should be
>
>   void far *p;
>   ...
>   p = MK_FP(0xFFFFu, 0xE000u);

Actually, I have no idea what (if anything) might be at FFFF:E000,
but to consider another example---screens---a `better' way to write
this is something like:

	union screendata {
		short	sd_xc;		/* extended character */
		struct {
			char sd_ch;	/* character */
			char sd_attr;	/* attribute */
		} sd_un;
	};

	#define SCREENSEG	0xe800	/* or whatever */
	#define SCREENBASE ((union screendata far *)MK_FP(SCREENSEG, 0))

or even just

	#define SCREENBASE ((union screendata far *)0xe8000000)

or whatever.  The point is to hide the fact that this is an `absolute
address', and the way it is built, as much as possible, and to use a
meaningful symbol rather than a magic number.  That way when the next
instance of the system has the screen at a different address, you need
only change one `define' and maybe add some initialization code:

	extern union screendata far *screenbase;
	#define SCREENBASE screenbase

All of this should be used only to build the lowest level abstraction
(a `screen' would then become something you could print to, say) on
which you build the next level (windows, perhaps).
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov