addresses. We express bytes as two digit hex numbers
(0x00 to 0xFF) and words as four digit hex numbers
(0x0000 to 0xFFFF) [where the leading 0x just means that
it is a hex number]. It then follows that in Figure 1, the
addresses are words and the data are bytes. We use ‘…’ to
indicate that there are addresses and data before and after
what is shown.
In this specific case, we see addresses 0x0400 to
0x040C (decimal 1024 to 1036) and we see a random
appearing sequence of data for each address beginning
with 0x48 and ending with 0x00. Then, we see ‘…’ to
show us that further along at the addresses 0x0678 and
0x0679 we have the data value 0x04 and 0x00. We
assume that there is lots of other data at the other
addresses, but since we aren’t showing them they aren’t
needed for this explanation. The first sequence of bytes
aren’t as random as they appear. They are the ASCII codes
[link: www.asciitable.com] for the characters ‘Hello
World!’ followed by the null byte 0x00 that to C indicates
the end of a string.
What Do You Call Eight bits?
Originally, C had data types with names like char or
int and the size of these data types was machine
dependent. K&R ( The C Programming Language, Brian
Kernighan and Dennis Ritchie, 2nd edition) defines char:
‘a single byte, capable of holding one character from the
local character set.’ Since that character set is ASCII, you
only need seven bits to encode it. The extra bit is used as
a sign bit leading to the bizarre concept (IMHO) of signed
and unsigned char. A signed character has values of –128
to 127, and an unsigned character has a value of 0 to 255.
There are no negative ASCII characters nor are there any
above 127 (in the basic set). The sign lets you use chars as
ordinary numbers within the ranges shown above but
confuses novices who ask: “Is char a number or a
character?”
C has grown a bit since K&R and the C99 standards
library defined terms that help make data type more
specific and portable by giving them known numbers of
bits for a given type. This convention uses the data types
int8_t and uint8_t for the unsigned and signed eight-bit
types (formerly char), and int16_t and uint16_t for 16-bit
data types (formerly int). That’s a lot clearer, isn’t it? Well,
not to me, but after we get past this introductory article,
we will stop using the original K&R C names and start
using those from C99.
A Few Pointers
68 June 2010
Suppose you have the task of writing a function that
sends strings of characters out the serial port. There would
be many ways to do this, but one way would be to
provide that function the address of the first character in a
string. Then, the function could send out that character,
add one to the address, and send each subsequent
character until it runs into the character that C considers
to end a string: nul (0x00) that we mentioned above. Such
a function operating on the data in Figure 1 would send
‘Hello World!’ on the serial port. A function like this would
need some way to get the address of the string. In C, we
can send that address in the function parameter list by
using a pointer. In C, we use ‘*’ to indicate that a variable
is a pointer. We’ll see this again shortly.
Pointers Can Be Dangerous
Pointers are the reason that many refer to C as a
mid-level rather than a high level programming
language. In high level languages, the programmer
only deals with data and the compiler makes all the
decisions about the addresses. In low level languages
(like assemblers), the programmer assigns the addresses
to the data. In C, we are not required to play with
addresses, but are allowed to if we want to. Some things
can only be done using pointers. Pointers also allow us
to do many things more efficiently and cleverly than
would otherwise be the case. But they can be dangerous.
To quote K&R, p 93: “Pointers have been lumped with
the goto statement as a marvelous way to create
impossible to understand programs. This is certainly true
when they are used carelessly, and it is easy to create
pointers that point somewhere unexpected. With
discipline, however, pointers can also be used to achieve
clarity and simplicity.” This would be a good time to
assert that if you really want to learn the C programming
language, you should get K&R. Books like my C
Programming for Microcontrollers (available from Nuts &
Volts) are also good for getting started specifically with
micros, but to really get the religion, you need a copy of
the “bible” and K&R is it.
As an example of a dangerous misuse of pointers, I
once used a pointer to sequentially access the video
buffer of an IBM PC. I made a simple ‘fence-post’ error,