Generic C
Volume Number: 7
Issue Number: 9
Column Tag: Beginning C
Generic C with a Twist
By Kirk Chase, MacTutor Editor
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Introduction
I suppose a good many readers are interested in programming on the Macintosh,
but have never done so before. I also suppose that a good many of you are taking
computer science classes in school or college. And I also suppose that many of you are
forced to do your development work on a Pretty Crummy computer rather than a
Macintosh.
Unfortunately, there are a number of reasons why you are forced away from
using your development platform of choice.
1. The Mac is a difficult machine to program for. Even if the program is simple.
2. The assistants and code help is all geared for other platforms.
3. Your class load does not permit you the time to develop Mac programs.
Well, there is help. The major C languages supported on the Mac also support
generic C programs with little or no modifications. Most of them support all the ANSI
standard functions and UNIX functions as they make sense on the Macintosh. Also this
article will help you develop generic C programs on the Mac. Since cost is usually a
high consideration for students, I will suppose that you are using Symantec’s THINK C
for development work. This article will explain some of the techniques of how to create
source-portable code and other interesting things you can do with THINK C.
Figure 1: A Generic C Program
Figure 2: A Generic THINK C Program
First: Preprocessors
Since this article is discussing writing source-portable code, C preprocessors
are used quite frequently. They can be used for including files, defining and undefining
flags, as well as directing conditional compilation. Using C preprocessors wisely will
allow you to write one source and compile it on multiple platforms.
Only one preprocessor is automatically defined for you. THINK_C is defined
when working with THINK C. You can test for it with the #ifdef or #ifndef
preprocessors as well as undefine it with #undef. Unfortunately there is no
preprocessor automatically defined when the source debugger option is turned on; this
would greatly reduce the mistakes of not defining or undefining a debugger symbol
(more later).
With the #if-#endif or #if-#else-#else directives you can section which code
will be compiled. Thereby you can write purely generic code and code slightly tweaked
for the Macintosh. For example, you would use
* 1 */
#ifdef THINK_C
/* code that is THINK C specific */
#else
/* generic replacement C code */
#endif
One convention that I like in THINK C is the one time header file inclusion. If
your header file in named “filename.h”, you can include a preprocessor directive,
“#define _H_filename” and the header file will be included only once no matter how
many files #include “filename.h”. This keeps things from being multiply defined.
I use the #pragma directives for navigation. There is a shareware product by
Max Lyth called, “CMarker”. Once installed a box is added to source code windows.
When pressed a list of functions appear as well as points marked in your code like the
following: #pragma mark ( is displayed). THINK C
currently ignores the #pragma directive and CMarker scans for #pragma mark. When
a mark or function is selected, the source code will scroll to that place automatically.
You can also comment/uncomment blocks of code automatically with CMarker. There
are also other commercial and shareware products that can do similar functions.
Floating Down The Standard Streams
The standard streams-stdin, stdout, and stderr-are also supported by THINK C.
Upon using a routine that accesses a standard stream, such as printf() or scanf(),
THINK C creates a window named “console” that simulates a display of 80 columns by
25 lines. The console window is used by all the standard streams. A menu bar is
created, if one is not already provided, with options to quit as well as cut, copy, and
paste text. You already have a simple Mac program without any extra work on your
part. You may even use the standard streams in Macintosh applications (output only);
in this way, printf() could be used like a call to fprintf() to stderr.
Input, through stdin, defaults to line-buffered, echoed input with full editing
capabilities. This means that your input is held from the program until you type
RETURN or ENTER (these keys are not passed). You can also use the menu commands as
well as the DELETE or BACKSPACE key. There are other input modes that allow for