|
|
|
Interactive CInteractive C (IC for short) is a C language dialect consisting of a compiler (with interactive command-line compilation and debugging) and a run-time machine language module. IC implements a subset of C including control structures (for, while, if, else), local and global variables, arrays, pointers, 16-bit and 32-bit integers, and 32-bit floating point numbers. IC does not implement some of C's more complex features, including structures and unions. IC works by compiling into pseudo-code for a custom stack machine, rather than compiling directly into native code for a particular processor. This pseudo-code (or p-code) is then interpreted by the run-time machine language program. This unusual approach to compiler design allows IC to offer the following design tradeoffs:
Since IC's ultimate performance is limited by the fact that its output p-code is interpreted, its advantages are taken at the expense of raw execution speed. Getting Started (on Windows NT/95/98)This section describes how to boot IC on the RoboBoard using the Windows NT machines located in the ELEC 201 laboratory. These instructions also apply to any computer running Windows 95, Windows 98, or Windows 2000.
At this point you are ready to load a C program or evaluate expressions typed in the command window. For more information on "getting started with Macintosh, Sun, or Owlnet computers", click here or see the bottom of this page. Using ICWhen running and attached to the RoboBoard, C expressions, function calls, and IC commands may be typed at the IC> prompt. All C expressions must be ended with a semicolon. For example, to evaluate the arithmetic expression 1 2, type the following:
When this expression is typed, it is compiled by the console computer and then downloaded to the RoboBoard for evaluation. The 68HC11 on the RoboBoard then evaluates the compiled form and returns the result, which is printed on the console computer's screen. To evaluate a series of expressions, create a C block
by beginning with an open curly brace ``
IC CommandsIC responds to the following commands:
Line EditingIC has a built-in line editor and command history, allowing editing and re-use of previously typed statements and commands. The mnemonics for these functions are based on the control key assignments employed in the Emacs editor (NOTE: This functionality is not currently available on the Windows NT machines): To scan forward and backward in the command history, type CTRL-P
or An earlier line in the command history can be retrieved by typing the exclamation point followed by the first few characters of the line to retrieve, and then the space bar. IC does parenthesis-balance-highlighting as expressions are typed. (This feature is currently disabled in the Win32 version). Figure 10.1
shows the keystroke mappings understood by IC.
In addition to the built-in line editor, IC on the Macintoshes supports standard Macintosh editing features using the mouse. These include copy and paste. Anywhere within the IC window, you can highlight text within that window, and can "copy" it with the key-sequence Command-C. Copying adds the text to the clipboard, which allows you to paste it on a subsequent IC command line with Command-V. The main() FunctionAfter functions have been downloaded to the RoboBoard, they can be invoked from the IC prompt. If one of the functions is named main(), it will automatically be run when the RoboBoard is reset. To reset the RoboBoard without running the main() function (for instance, when hooking the RoboBoard back to the computer), hold down the CHOOSE button on the RoboBoard while pressing reset. Creating a C programTo create your C program, you need to use an editor to enter your program into a file. On the Macintosh, the editor currently installed is called Alpha. In Unix, you can use vi, emacs, xedit, or any other editor with which you are comfortable. Windows machines also have a plethora of editors; use the one with which you are most comfortable (and remember to save your files as text-only files!). A Quick C TutorialMost C programs consist of function definitions and data structures. Here is a simple C program that defines a single function, called main.
void main()
{
printf("Hello, world!\n");
}
All functions must have a return value; that is, the value that they return when they finish execution. main has a return value type of void, which is the "null" type. Other types include integers (int) and floating point numbers (float). This function declaration information must precede each function definition. Immediately following the function declaration is the function's name (in this case, main). Next, in parentheses, are any arguments (or inputs) to the function. main has none, but an empty set of parentheses is still required. After the function arguments is an open curly-brace "{", marking the start of the actual function code. Curly-braces signify program blocks, or chunks of code. Next comes a series of C statements. Statements demand that some action be taken. The demonstration program has a single statement, a printf (formatted print). This will print the message Hello, world! to the LCD display. The \n indicates an end-of-line character. The printf statement ends with a semicolon (;). All C statements must end with a semicolon. Beginning C programmers commonly make the error of forgetting the semicolon required at the end of each statement. The main function is ended by the close curly-brace "}". Here is another example demonstrating a few more features of C. The following code defines the function square, which returns the mathematical square of a number.
int square(int n)
{
return n * n;
}
The function is declared as type int, meaning it will return an integer value. Next comes the function name square, followed by its argument list in parentheses. square has one argument, n, an integer. Notice how declaring the argument type is done similarly to declaring the function type. When a function has arguments declared, those argument variables are valid within the "scope" of the function (i.e., they only have meaning within the function's own code). Other functions may use the same variable names independently. The code for square is contained within the set of curly braces. In fact, it consists of a single statement: the return statement. The return statement exits the function and returns the value of the C expression that follows it (in this case "n * n"). A set of precedence rules governs the order in which expressions are evaluated (see the table in Section 10.7.8). Since this example has only one operation (multiplication), signified by the "*", precedence in this case is not an issue. The following is an example of a function that performs a function call to the square program.
float hypotenuse(int a, int b)
{
float h; /* creates h */
h = sqrt((float)(square(a) + square(b))); /* provides the formula for h */
return h;
}
If a=3 and b=4, then h would equal the square root of 3 squared plus 4 squared, or 5.0 (because it is a floating point number, it will be represented in decimal notation). A few more features of C are demonstrated in this code. First, notice that the floating point variable h is defined at the beginning of the hypotenuse function. In general, whenever a new program block (indicated by a set of curly braces) is begun, new local variables may be defined. The value of h is set to the result of a call to the sqrt function. It turns out that sqrt is a built-in function that takes a floating point number as its argument. If the square function (defined earlier) were to be used inside the sqrt function, a type incompatibility problem would come up, since the square function sends an integer result, but the sqrt function requires a floating point argument. To get around the type incompatibility, the integer sum (square(a) + square(b)) can be coerced or cast into a float by preceding it with the desired type, in parentheses. The integer sum is made into a floating point number and then passed along to sqrt. The hypotenuse function finishes by returning the value of h. Commenting your code is very important. Throughout this manual, code will be explained in comments. A comment can be added by using /* to open your comment and by using */ to close your comment. Frequent comments will make it easier for you to understand what your program is doing. Also, it will make it much easier for your partners to follow code written while they were not there. This concludes the brief C tutorial. A much more detailed tutorial is available on-line. Data Types, Operations, and ExpressionsVariables and constants are the basic data objects in a C program. Declarations list the variables to be used, state what type they are, and may set their initial value. Operators determine what is to be done to them. Expressions combine variables and constants to create new values. Variable NamesVariable names are case-sensitive. The underscore character is allowed and is often used to enhance the readability of long variable names. C keywords like if, while, etc. may not be used as variable names. Global variables and functions cannot have the same name. In addition, local variables with the same name as functions prevent the use of that function within the scope of the local variable. Further, local variables with the same name as global variables prevent use of the global variables within the scope of the local variable. Data TypesIC supports the following data types: 16-bit Integers16-bit integers are signified by the type indicator int. They are signed integers, and may be valued from 32,768 to 32,767 decimal. 32-bit Integers32-bit integers are signified by the type indicator long. They are signed integers, and may be valued from 2,147,483,648 to 2,147,483,647 decimal. 32-bit Floating Point NumbersFloating point numbers are signified by the type indicator float. They have approximately seven decimal digits of precision and are valued from about 10to 10. 8-bit CharactersCharacters are an 8-bit number signified by the type indicator char. A character's value typically represents a printable symbol using the standard ASCII character code. Arrays of characters (character strings) are supported, but individual characters are not. Local and Global VariablesIf a variable is declared within a function, or as an argument to a function, its binding is local, meaning that the variable is recognized only within that function definition. Variables declared outside of a function are global variables. They are defined for all functions, including functions defined in other files (outside the file where it was declared). Variable InitializationLocal and global variables can be initialized when they are declared. If no initialization value is given, the variable is initialized to zero.
int foo()
{
int x; /* create local variable x
with the default initial value of 0 */
int y = 7; /* create local variable y
with initial value 7 */
...
} /* end of foo */
float z = 3.0; /* create global variable z
with initial value 3.0 */
Local variables are initialized whenever the function containing them runs. Global variables are initialized whenever a reset condition occurs. Reset conditions occur when:
Persistent Global VariablesA special uninitialized form of global variable, called the ``persistent'' type, has been implemented in IC. A persistent global is not initialized upon the conditions listed for normal global variables. To declare a persistent global variable, prefix the type specifier with the key word persistent. For example, the statement
creates a global integer called i. The initial value for a persistent variable is arbitrary; it depends on the contents of RAM that were assigned to it. Initial values for persistent variables cannot be specified in their declaration statement. Persistent variables keep their value when the robot is turned off and on, when main is run, and when system reset occurs. Persistent variables, in general, will lose their value when a new program is downloaded. However, it is possible to prevent this from occurring. If persistent variables are declared at the beginning of the C program code, before any function or non-persistent globals, they will be re-assigned to the same location in memory when the code is re-compiled, and thus their values will be preserved over multiple downloads. If the program is divided into multiple files and it is desired to preserve the values of persistent variables, then all of the persistent variables should be declared in one particular file and that file should be placed first in the load ordering of the files.
ConstantsInteger ConstantsIntegers may be defined in decimal integer format (e.g., 4053 or -1), hexadecimal format using the ``0x'' prefix followed by hexadecimals a through f (e.g., 0x1fff), and a non-standard but useful assembly language binary format using the ``0b'' prefix (e.g., 0b1001001). Octal constants using the zero prefix are not supported. Long Integer ConstantsLong integer constants are created by appending the suffix ``l'' or ``L'' (upper- or lower-case alphabetic L) to a decimal integer. For example, 0L is the long zero. Either the upper or lower-case ``L'' may be used, but upper-case is the convention for readability. Floating Point ConstantsFloating point numbers may use exponential notation (e.g., `` 10e3'' or ``10E3'') or must contain the decimal period. For example, the floating point zero can be given as ``0.'', `` 0.0'', or ``0E1'', but not as just ``0''. Characters and Character StringsQuoted characters return their ASCII value (e.g., 'x'). Character strings are defined with quotation marks, e.g., "This is a character string.". OperatorsFor each data type (int, float, etc.), a particular set of operators determines the operations that can be performed on them. IntegersThe following operations are supported on integers:
Long IntegersA subset of the operations implemented for integers are implemented for long integers: arithmetic addition +, subtraction -, and multiplication *, and the integer comparison operations. Bitwise and boolean operations and division are not supported. Floating Point NumbersIC uses a package of public-domain floating point routines distributed by Motorola. This package includes arithmetic, trigonometric, and logarithmic functions. A word of caution: floating point functions are much slower than integer operations on the 68HC11 processor. The following operations are supported on floating point numbers:
CharactersCharacters are only allowed in character arrays. When a cell of the array is referenced, it is automatically coerced into a integer representation for manipulation by the integer operations. When a value is stored into a character array, its upper eight bits are truncated, forcing a standard 16-bit integer into an 8-bit character. Assignment Operators and ExpressionsThe basic assignment operator is =. The following statement adds 2 to the value of a.
a = a + 2;
The abbreviated form
a += 2;
could also be used to perform the same operation.
All of the following binary operators can be used in this fashion:
+ - * / % << >> & ^ |
Increment and Decrement OperatorsThe increment operator ``++'' increments the named variable. For example, the statement ``a++'' is equivalent to ``a = a+1'' or ``a += 1''. A statement that uses an increment operator has a value. If the increment operator comes after the named variable, then the value of the statement is calculated after the increment occurs. Otherwise, the value of the statement is calculated after the increment. The following example should clarify these differences:
int a = 3; /* assign the initial value of the two variables */
int b = 5;
printf(``a=%d b=%d\n'', a, b); /* a = 3, b = 5 */
b = a++; /* increments a after setting b = a */
printf(``a=%d b=%d\n'', a, b); /* a = 4, b = 3 */
b = ++a /* increments a before setting b = a */
printf(``a=%d b=%d\n'', a, b); /* a = 5, b = 5 */
The first increment operator equalizes the two variables before increasing the value of a, while the second increments beforehand. The difference results from the placement of the ``a++'' operator. The decrement operator ``-'' is used in the same fashion as the increment operator. Precedence and Order of EvaluationThe following table summarizes the rules for precedence and associativity for the C operators. Operators listed earlier in the table have higher precedence; operators on the same line of the table have equal precedence.
Control FlowIC supports most of the standard C control structures. Notable exceptions are the case and switch statements, which are not supported. |