[Courses] [C] Why so many types? (Re: Current topic: variables in C.)

Julie jockgrrl at austin.rr.com
Sun Jun 9 11:52:43 EST 2002

Mary wrote:

> OK, here's a small summary, others may want to contribute more:
> This summary should be understanbable by anyone who has played with the
> basic C types: int, char, float and so on...
> The basic model of a computer processer is that values are loaded from
> memory into registers, which are pieces of memory directly accessible to
> the CPU. The CPU can not manipulate values from memory, it can only
> access the registers.

This is true for load-and-store architectures, such as most of
the modern RISC architectures.  It is not true of the CISC
architectures.  VAXen were able to do anything and everything
(just about ...) without ever using a register -- except perhaps
the program counter and stack pointer as relative address
registers for operands out in real memory.  On a CISC box, such
as a VAX, it would be possible to write

	addl3	a, b, c

where memory location "a" is added to "b" and the result stored
in "c".  On a load-and-store architecture that might be written

	ld	r0, a
	ld	r1, b
	add	r0, r1
	st	r0, c

Before anyone goes "But why would someone want four instructions
where they can use just one?", then answer is that often RISC
machines can execute those four instuctions in the same amount
of time, or perhaps even less, than the CISC architecture needs
to execute that one instruction.

For example, on a VAX addl3 is a single byte, then you have the
three operands, which in the example above (since it's an
addressing mode which requires "register indirect with offet"
as an addressing mode), you've got the addressing mode operand
plus it's 4-byte offset, times three operands, or 15 bytes worth
of operand opcodes.  Add that to the single-byte instruction
and you get 16 bytes for one instruction.  Coincidentally, that's
the same number of bytes worth of opcodes for the 4 RISC
instructions.  Except the instruction fetch and decode part of
the RISC machine knows that all of its operands are 4 bytes long
and it can begin instruction decode on multiple instructions at
the same time, perhaps even performing multiple instructions at
the same time.  The CISC box doesn't have a clue where the next
instruction is until it's fetched the third addressing mode.
And of course, it also has to fetch the values of the operands.

> There are a very small number of registers, somewhere in the range of
> ten to fifty depending on your processor model (and they're much faster
> to access than RAM too). There are two types of register for storing
> data - integer registers, and floating point registers.
> The reason for this is that there are some differences between
> performing arithmetic on integer (whole number) data and floating point
> (real number data, stored to a limited number of significant figures)
> arithmetic and the processer does integer arithmetic differently from
> floating point arithmetic. So C makes this distinction too.


> Now, different processors have different size registers. Some have 16
> bit registers (they can store 2^16 different numbers), some have 32 bit
> registers (they can store 2^32 different numbers) and some have 64 bits,
> or 8 bits. This is why C integers are not meant to be a specific size.

And some have no registers, or registers with sizes in multiples
of 6 bits, such as 36, 48 and 60.

The idea really is to abstract "integer" sizes so that "short"
can hold small numbers, "int" can hold larger numbers and "long"
can hold Really Big Numbers.  "long" typically is large enough
to hold an integer which can represent every word in memory, or
every location on disk, as a value.  When disks became Really
Huge we started to see more "long long" types creep into the
language.  This is also part of the motivation for 64-bit
architectures -- huge address spaces and databases.

> OK, that's a small summary. I'm not familiar with floating point stuff
> much, so someone else may want to explain why we have floats and
> doubles, and how big they are.

The same sort of reasons.  But also, at the time C was created,
a lot of machines didn't have a floating point math unit.  My
first UNIX box did all of it's floating point math the hard way --
it didn't even have 32-bit multiple or divide.  The only 32-bit
math instructions it even had were add and subtract.  Multiply
was 16x16=32 and divide was 32/16=16.

Floats have typically been on the order of 16 or 32 bit, with 32
bit floats becoming more popular as more CPUs have built-in floating
point hardware.  Doubles were typically twice the size of a float,
so if "float" was 16-bits, "double" was 32 and so on.
Julianne Frances Haugh             Life is either a daring adventure
jockgrrl at austin.rr.com                 or nothing at all.
					    -- Helen Keller

More information about the Courses mailing list