467 lines
21 KiB
HTML
467 lines
21 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>Programming Bits: C# Data Types LG #85</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="foolish.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue85/ortiz.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<TABLE BORDER><TR><TD WIDTH="200">
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<IMG ALT="LINUX GAZETTE" SRC="../gx/2002/lglogo_200x41.png"
|
|
WIDTH="200" HEIGHT="41" border="0"></A>
|
|
<BR CLEAR="all">
|
|
<SMALL>...<I>making Linux just a little more fun!</I></SMALL>
|
|
</TD><TD WIDTH="380">
|
|
|
|
|
|
<CENTER>
|
|
<BIG><BIG><STRONG><FONT COLOR="maroon">Programming Bits: C# Data Types</FONT></STRONG></BIG></BIG>
|
|
<BR>
|
|
<STRONG>By <A HREF="../authors/ortiz.html">Ariel Ortiz Ramirez</A></STRONG>
|
|
</CENTER>
|
|
|
|
</TD></TR>
|
|
</TABLE>
|
|
<P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
In my <a href="../issue84/ortiz.html"> previous
|
|
article</a>, I introduced the C# programming language and
|
|
explained how it works in the context of the Mono environment, an open-source
|
|
implementation of Microsoft's .NET framework. I will now go on to some details
|
|
on the data types supported by the C# programming language.</p>
|
|
|
|
<p>In the subsequent discussion I will use the following diagrammatic notation
|
|
to represent variables and objects:</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/notation.png" width="363" height="151" alt="Variable and object diagram notation."></p>
|
|
|
|
<p>The variable diagram is a cubic figure that depicts three traits (name, value
|
|
and type) relevant during the compilation and execution of a program. In the von
|
|
Neumann architecture tradition, we will consider a variable as a chunk of memory
|
|
in which we hold a value that can be read or overwritten. The object diagram is
|
|
a rounded edge rectangle that denotes an object created at runtime and allocated
|
|
in a garbage collectable heap. For any object in a certain point in time, we
|
|
know what type (class) it is, and the current values of its instance
|
|
variables. </p>
|
|
|
|
<h2>Type Categories</h2>
|
|
|
|
<p>In the C# programming language, types are divided in three categories: </p>
|
|
|
|
<ul>
|
|
<li>value types</li>
|
|
<li>reference types </li>
|
|
<li>pointer types</li>
|
|
</ul>
|
|
<p>In a variable that holds a <b>value type</b>, the data itself is directly
|
|
contained within the memory allotted to the variable. For example, the following
|
|
code</p>
|
|
<blockquote>
|
|
<pre>int x = 5;</pre>
|
|
|
|
</blockquote>
|
|
<p>declares an 32-bit signed integer variable, called <code>x</code>,
|
|
initialized with a value of 5. The following figure represents the corresponding
|
|
variable diagram:</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/intvar.png" width="136" height="102" alt="A simple int variable diagram."></p>
|
|
|
|
<p>Note how the value 5 is contained within the variable itself.</p>
|
|
|
|
<p>On the other hand, a variable that holds a <b>reference type</b> contains the
|
|
address of an object stored in the heap. The following code declares a variable
|
|
called <code>y</code> of type <code>object</code> which gets initialized, thanks
|
|
to the <code>new</code> operator, so that it refers to a new heap allocated <code>object</code>
|
|
instance (<code>object</code> is the base class of all C# types, but more of
|
|
this latter).</p>
|
|
|
|
<blockquote>
|
|
<pre>object y = new object();</pre>
|
|
|
|
</blockquote>
|
|
<p>The corresponding variable/object diagram would be:</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/objectvar.png" alt="An object diagram." width="290" height="159"></p>
|
|
|
|
<p>In this case, we can observe that the "value" part of the variable
|
|
diagram contains the start of an arrow that points to the referred object.
|
|
This arrow represents the address of the object inside the memory
|
|
heap. </p>
|
|
|
|
<p>Now, let us analyze what happens when we introduce two new variables and do
|
|
some copying from the original variables. Assume we have the following code:</p>
|
|
|
|
<blockquote>
|
|
<pre>int a = x;
|
|
object b = y; </pre>
|
|
|
|
</blockquote>
|
|
<p>The result is displayed below: </p>
|
|
|
|
<p><img border="0" src="misc/ortiz/copying.png" width="473" height="282" alt="Results after copying values and references."></p>
|
|
|
|
<p>As can be observed, <code>a</code> has a copy of the value of <code>x</code>.
|
|
If we modify the value of one of these variables, the other variable would
|
|
remain unchanged. In the case of <code>y</code> and <code>b</code>, both
|
|
variables refer to the same object. If we alter the state of the object using variable
|
|
<code>y</code>, then the resulting changes will be observable using variable <code>b</code>,
|
|
and vice versa.</p>
|
|
|
|
<p>Aside from references into the heap, a reference type variable may also
|
|
contain the special value <code>null</code>, which denotes a nonexistent object.
|
|
Continuing with the last example, if we have the statements</p>
|
|
|
|
<blockquote>
|
|
<pre>y = null;
|
|
b = null;</pre>
|
|
|
|
</blockquote>
|
|
<p>then variables <code>y</code> and <code>b</code> no longer refer to any
|
|
specific object, as shown below:</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/nullvar.png" width="469" height="196" alt="Making references equal to null."></p>
|
|
|
|
<p>As can be seen, all references to the object instance have been lost. This
|
|
object has now turned into "garbage" because no other live reference to it
|
|
exists. As noted before, in C# the heap is garbage collected, which means that
|
|
the memory occupied by these "dead" objects is at sometime
|
|
automatically disposed and recycled by the runtime system. Other languages, such
|
|
as C++ and Pascal, do not have this kind of automatic memory management scheme.
|
|
Programmers for these languages must explicitly free any heap allocated memory
|
|
chunks that the program no longer requires. Failing to do so gives place to
|
|
memory leaks, in which certain portions of memory in a program are wasted
|
|
because they haven't been signaled for reuse. Experience has shown that explicit memory de-allocation is
|
|
cumbersome and error prone. This is why many modern programming languages (such as Java,
|
|
Python, Scheme and Smalltalk, just to name a few) also incorporate garbage
|
|
collection as part of their runtime environment.</p>
|
|
|
|
<p>Finally, a <b>pointer type</b> gives you similar capabilities as those found
|
|
with pointers in languages like C and C++. It is important to understand that
|
|
both pointers and references actually represent memory addresses, but that's
|
|
where their similarities end. References are tracked by the garbage collector,
|
|
pointers are not. You can perform pointer arithmetic on pointers, but not on
|
|
references. Because of the unwieldy nature associated to pointers, they can only
|
|
be used in C# within code marked as <code>unsafe</code>. This is an advanced
|
|
topic and I won't go
|
|
deeper into this matter at this time.</p>
|
|
|
|
<h2>Predefined Types</h2>
|
|
|
|
<p>C# has a rich set of predefined data types which you can use in your
|
|
programs. The following figure illustrates the hierarchy of the predefined data types
|
|
found in C#:</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/types.png" width="576" height="226" alt="The C# type hierarchy."></p>
|
|
|
|
<p>Here is a brief summary of each of these types:</p>
|
|
|
|
<table border="0" cellpadding="10" bordercolorlight="#EBEBEB" bordercolordark="#000000" bordercolor="#FFFFFF" cellspacing="1" bgcolor="#000000">
|
|
<tr>
|
|
<th style="background-color: #C0C0C0">Type</th>
|
|
<th style="background-color: #C0C0C0">Size in <br>
|
|
Bytes</th>
|
|
<th style="background-color: #C0C0C0">Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>bool</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">1</td>
|
|
<td bgcolor="#EBEBEB">Boolean value. The only valid literals are <code>true</code>
|
|
and <code>false</code>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>sbyte</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">1</td>
|
|
<td bgcolor="#EBEBEB">Signed byte integer.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>byte</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">1</td>
|
|
<td bgcolor="#EBEBEB">Unsigned byte integer.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>short</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">2</td>
|
|
<td bgcolor="#EBEBEB">Signed short integer.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>ushort</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">2</td>
|
|
<td bgcolor="#EBEBEB">Unsigned short integer.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>int</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">4</td>
|
|
<td bgcolor="#EBEBEB">Signed integer. Literals may be in decimal (default)
|
|
or hexadecimal notation (with an <code>0x</code> prefix). Examples: <code>26</code>,
|
|
<code>0x1A</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>uint</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">4</td>
|
|
<td bgcolor="#EBEBEB">Unsigned integer. Examples: <code>26U</code>, <code>0x1AU
|
|
</code>(mandatory <code>U</code> suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>long</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">8</td>
|
|
<td bgcolor="#EBEBEB">Signed long integer. Examples: <code>26L</code>, <code>0x1AL
|
|
</code>(mandatory <code>L</code> suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>ulong</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">8</td>
|
|
<td bgcolor="#EBEBEB">Unsigned long integer. Examples: <code>26UL</code>, <code>0x1AUL
|
|
</code>(mandatory <code>UL</code> suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>char</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">2</td>
|
|
<td bgcolor="#EBEBEB">Unicode character. Example: 'A' (contained within
|
|
single quotes)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>float</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">4</td>
|
|
<td bgcolor="#EBEBEB">IEEE 754 single precision floating point number.
|
|
Examples: <code>1.2F</code>, <code>1E10F </code>(mandatory <code>F</code> suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>double</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">8</td>
|
|
<td bgcolor="#EBEBEB">IEEE 754 double precision floating point number.
|
|
Examples: <code>1.2</code>, <code>1E10</code>, <code>1D</code> (optional <code>D</code>
|
|
suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>decimal</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">16</td>
|
|
<td bgcolor="#EBEBEB">Numeric data type suitable for financial and monetary
|
|
calculations, exact to the 28th decimal place. Example: <code>123.45M</code>
|
|
(mandatory <code>M</code> suffix)</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>object</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">8+</td>
|
|
<td bgcolor="#EBEBEB">Ultimate base type for both value and reference types.
|
|
Has no literal representation.</td>
|
|
</tr>
|
|
<tr>
|
|
<td bgcolor="#EBEBEB"><code>string</code></td>
|
|
<td align="right" bgcolor="#EBEBEB">20+</td>
|
|
<td bgcolor="#EBEBEB">Immutable sequence of Unicode characters. Example: <code>"hello
|
|
world!\n" </code>(contained within double quotes)</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p align="left">C#'s has a unified type system such that a value of any type can
|
|
be treated as an object. Every type in C# derives, directly or indirectly, from
|
|
the <code>object</code> class. Reference types are treated as objects simply by
|
|
viewing them as <code>object</code> types. Value types are treated as objects by
|
|
performing <i>boxing</i> and <i>unboxing</i> operations. I will go deeper into
|
|
these concepts in my next article.</p>
|
|
|
|
<h2>Classes and Structures</h2>
|
|
|
|
<p>C# allows you to define new reference and value types. Reference types are
|
|
defined using the <code>class</code> construct, while value types are defined
|
|
using <code>struct</code>. Lets see them both in action in the following
|
|
program:</p>
|
|
|
|
<blockquote>
|
|
<pre>struct ValType {
|
|
public int i;
|
|
public double d;
|
|
public ValType(int i, double d) {
|
|
this.i = i;
|
|
this.d = d;
|
|
}
|
|
public override string ToString() {
|
|
return "(" + i + ", " + d + ")";
|
|
}
|
|
}
|
|
|
|
class RefType {
|
|
public int i;
|
|
public double d;
|
|
public RefType(int i, double d) {
|
|
this.i = i;
|
|
this.d = d;
|
|
}
|
|
public override string ToString() {
|
|
return "(" + i + ", " + d + ")";
|
|
}
|
|
}
|
|
|
|
public class Test {
|
|
public static void Main (string[] args) {
|
|
|
|
// PART 1
|
|
ValType v1;
|
|
RefType r1;
|
|
v1 = new ValType(3, 4.2);
|
|
r1 = new RefType(4, 5.1);
|
|
System.Console.WriteLine("PART 1");
|
|
System.Console.WriteLine("v1 = " + v1);
|
|
System.Console.WriteLine("r1 = " + r1);
|
|
|
|
// PART 2
|
|
ValType v2;
|
|
RefType r2;
|
|
v2 = v1;
|
|
r2 = r1;
|
|
v2.i++; v2.d++;
|
|
r2.i++; r2.d++;
|
|
System.Console.WriteLine("PART 2");
|
|
System.Console.WriteLine("v1 = " + v1);
|
|
System.Console.WriteLine("r1 = " + r1);
|
|
}
|
|
}</pre>
|
|
|
|
</blockquote>
|
|
<p>First we have the structure <code>ValType</code>. It defines two instance
|
|
variables, <code>i</code> and <code>d</code> of type <code>int</code> and <code>double</code>,
|
|
respectively. They are declared as <code>public</code>, which means they can be accessed
|
|
from any part of the program where this structure is visible. The structure
|
|
defines a constructor, which has the same name as the structure itself and,
|
|
contrary to method definitions, has no return type. Our constructor is in charge
|
|
of the initialization of the two instance variables. The keyword <code>this</code>
|
|
is used here to obtain a reference to the instance being created and has to be
|
|
used explicitly in order to avoid the ambiguity generated when a parameter name
|
|
clashes with the an instance variable name. The structure also defines a method
|
|
called <code>ToString</code>, that returns the external representation of a
|
|
structure instance as a string of characters. This method overrides the <code>ToString</code>
|
|
method (thus the use of the <code>override</code> modifier) defined in this
|
|
structure's base type (the <code>object</code> class). The body of this method
|
|
uses the string concatenation operator (+) to generate a string of the form
|
|
"(<i>i</i>, <i>d</i>)", where <i>i</i> and <i>d</i> represent the
|
|
current value of those instance variables, and finally returns the expected
|
|
result.</p>
|
|
|
|
<p>As can be observed, the <code>RefType</code> class has basically the same
|
|
code as <code>ValType</code>. Let us examine the runtime behavior of variables
|
|
declared using both types so we can further understand their differences. The <code>Test</code>
|
|
class has a <code>Main</code> method that establishes the program entry point.
|
|
In the first part of the program (marked with the "PART 1" comment) we
|
|
have one value type variable and one reference type variable. This is how they
|
|
look after the assignments:</p>
|
|
|
|
<img border="0" src="misc/ortiz/v1r1.png" alt="Class and structure variable diagram." width="509" height="231">
|
|
|
|
<p>The value type variable, <code>v1</code>, has its instance variables contained
|
|
within the variable itself. The <code>new</code> operator used in the assignment</p>
|
|
|
|
<blockquote>
|
|
<pre>v1 = new ValType(3, 4.2);</pre>
|
|
|
|
</blockquote>
|
|
<p>does not allocate any memory in the heap as we've learned from other
|
|
languages. Because <code>ValType</code> is a value type, the new operator is
|
|
only used in this context to call its constructor and this way initialize the
|
|
instance variables. Because <code>v1</code> is a local variable, it's actually
|
|
stored as part of the method's activation record (stack frame), and it exists
|
|
just because it's declared. </p>
|
|
|
|
<p>Objects referred by reference type variables have to be created explicitly at
|
|
some point in the program. In the assignment</p>
|
|
|
|
<pre> r1 = new RefType(4, 5.1);</pre>
|
|
|
|
<p>the <code>new</code> operator does the expected dynamic memory allocation
|
|
because in this case <code>RefType</code> is a reference type. The corresponding
|
|
constructor gets called immediately afterwards. Variable <code>v2</code> is also
|
|
stored in the method's activation record (because it's also a local variable)
|
|
but it's just big enough to hold the reference (address) of the newly created
|
|
instance. All the instance's data is in fact stored in the heap.</p>
|
|
|
|
<p>Now lets check what happens when the second part of the program (marked after
|
|
the "PART 2" comment) is executed. Two new variable are introduced and
|
|
they are assigned the values of the two original ones. Then, each of the
|
|
instance variables of the new variables are incremented by one (using the <code>++</code>
|
|
operator).</p>
|
|
|
|
<p><img border="0" src="misc/ortiz/v2r2.png" alt="Class and structure instances after copying." width="442" height="393"></p>
|
|
|
|
<p>When <code>v1</code> is copied into <code>v2</code>, each individual instance
|
|
variable of the source is copied individually into the destination, thus
|
|
producing totally independent values. So any modification done over <code>v2</code>
|
|
doesn't affect <code>v1</code> at all. This is not so with <code>r1</code> and <code>r2</code>
|
|
in which only the reference (address) is copied. Any change to the object
|
|
referred by <code>r2</code> is immediately seen by <code>r1</code>, because they
|
|
both refer in fact to the same object.</p>
|
|
|
|
<p>If you check the type hierarchy diagram above, you will notice that simple
|
|
data types such as <code>int</code>, <code>bool</code> and <code>char</code> are
|
|
actually <code>struct</code> value types, while <code>object</code> and <code>string</code>
|
|
are <code>class</code> reference types.</p>
|
|
|
|
<p>If you want to compile and run the <a href="misc/ortiz/varsexample.cs.txt">source
|
|
code</a> of the above example, type at the Linux shell prompt:</p>
|
|
|
|
<blockquote>
|
|
<pre>mcs varsexample.cs</pre>
|
|
|
|
<pre>mono varsexample.exe</pre>
|
|
|
|
</blockquote>
|
|
|
|
<p>The output should be:</p>
|
|
|
|
<blockquote>
|
|
|
|
<pre>PART 1
|
|
v1 = (3, 4.2)
|
|
r1 = (4, 5.1)
|
|
PART 2
|
|
v1 = (3, 4.2)
|
|
r1 = (5, 6.1)</pre>
|
|
|
|
</blockquote>
|
|
|
|
<h2>Resources</h2>
|
|
|
|
<dl>
|
|
<dt> <a href="http://www.go-mono.com/">http://www.go-mono.com/</a></dt>
|
|
<dd>The official Mono home page. You can find here the download and install instructions
|
|
for the Mono platform. It includes a C# compiler, a runtime environment, and
|
|
a class library.</dd>
|
|
<dt><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscon/html/vcoriCStartPage.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cscon/html/vcoriCStartPage.asp</a></dt>
|
|
<dd>General information on the C# programming language.</dd>
|
|
</dl>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<hr>
|
|
<CENTER><SMALL><STRONG>
|
|
Copyright © 2002, Ariel Ortiz Ramirez.
|
|
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
|
|
Published in Issue 85 of <i>Linux Gazette</i>, December 2002
|
|
</STRONG></SMALL></CENTER>
|
|
<!-- *** END copyright *** -->
|
|
<HR>
|
|
|
|
<!--startcut ==========================================================-->
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="foolish.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue85/ortiz.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../lg_faq.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="qubism.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|