Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!elroy.jpl.nasa.gov!usc!snorkelwacker.mit.edu!hsdndev!cmcl2!adm!smoke!gwyn From: gwyn@smoke.brl.mil (Doug Gwyn) Newsgroups: comp.lang.c Subject: Re: Dereferencing Typecast Integer Literals Message-ID: <15067@smoke.brl.mil> Date: 4 Feb 91 16:53:22 GMT References: <22700@netcom.UUCP> Organization: U.S. Army Ballistic Research Laboratory, APG, MD. Lines: 87 In article <22700@netcom.UUCP> avery@netcom.UUCP (Avery Colter) writes: >Now, obviously, in C, the most obvious way to do any of these is to declare >a char pointer. Dereferencing this pointer as an r-value PEEKs, dereferencing >it as an l-value POKEs, and dereferencing it with a parameter list postfixed >CALLs. In some implementations the latter is not supported, and the specific integral type needed to hold a data "address" for such usage is implementation dependent. (So be careful!) >However..... since all pointer objects are pseudo-integer in nature, and since >they are considered to be typecast cousins of the true integers, my question >is whether it is necessary to even declare a pointer for these tasks. I don't understand that at all. In C, each object consists of one or more bytes, and within (also "one past") an object a linear address space model is assumed. Also, each implementation is required to provide SOME integral type to which any data pointer can be cast such that upon subsequent cast back to the same type of pointer, the new pointer value will compare equal to the old value. This may actually involve some weird run-time implementation of "pointer equivalence classes", depending on what the machine architecture is like. >1. Since a constant literal integer of the appropriate size for the >implementation can be typecast into a pointer to any type, is it then >possible to dereference the result of this typecast expression? The major premise is false. It is NOT required that an arbitrary integral value be convertable to an object pointer, only that some suitable representation as an integer (of the implementation-dependent type) exist for each object pointer that is valid in the higher-level C abstract-machine model. In particular, there may be a range of "addresses" that are completely inaccessible from a C program; this is usually the case for virtual-memory operating systems and others that have separate physical address spaces for user versus supervisor tasks. Also, even if the memory is accessible from C, you have to obey object alignment constraints; for example, full-word accesses may require that the integer representation be a number that is exactly divisible by 2 or by 4. >s = *(char *)0xC000; /* C000: address of the keyboard strobe on Apple II */ On most Apple II C compilers, this would indeed pick up the data at that "soft switch" location. You need to be aware that in some cases (although not likely in this case) the compiler can generate multiple accesses to the location even though you have specified it only once in the source code. For I/O registers, including Apple II soft switches, there are often side effects from an access, such as clearing a flip-flop, and many locations behave differently for read versus write access. ANSI C has introduced the "volatile" type qualifier to provide a handle for the C programmer to try to obtain as near to a one-to-one mapping between the explicit source code and the generated machine instructions as possible; in older C implementations one simply had to be aware of what code would be generated for certain C constructs and then make sure that the proper constructs were used to obtain the desired effect. It is still highly recommended that you inspect the generated code to make sure that you are getting the desired effect. >2. If #1 can be done, then can a dereferenced typecast integer constant >be used as an l-value? >*(char *)0xC010 = 0; /* C010: value zeroed to signal ready to take another > character into C000 */ Sure, why not? Once the integer has been converted to a pointer, you are back in the domain of standard C. >3. Can a DTIC have a parameter list postfixed to make it into a function >call? There is no guarantee that this will work, although some implementations will support it. >*(void (*()))0xFC58(); /* FC58: address of firmware HOME function */ This, however, is not syntactically correct. You should instead try ((void (*)())0xFC58)(); or if your compiler is brain-damaged (*(void (*)())0xFC58)(); >What's the consensus on all this? Is it better to just declare const >pointer objects for all the firmware points you wish to have on hand? Recommended practice is to define macros for such accesses, using yet other macros that implement generic access of a certain type. E.g. #define PEEK(addr,type) (*((type)*)(addr)) #define KBDSTROBE PEEK(0xC000,char)