Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced C 1992

.pdf
Скачиваний:
92
Добавлен:
17.08.2013
Размер:
4.28 Mб
Скачать

Decimal, Binary, Hex, and Octal

C C C

 

C5C

 

C C C

 

C

makes the decimal-number characters fully usable. Octal is used for DEC minicomputers, and C was developed on DEC minicomputers—therefore, the support for octal. Figure 5.5 shows a representation of the octal numbers, which are similar to the ones in the decimal-based systems; octal, however, doesn’t have numbers 8 or 9.

Figure 5.5. Octal numbers 0 through 7.

When the 1992 example is represented in octal, it becomes 3710. This rather misleading number is as long as its decimal equivalent (and could have been longer). Without some form of prefix (or postfix) notation, you have no way to determine whether any number is octalor decimal-based (3710 is a legitimate number).

Look at Figure 5.6 to see how that octal value for 1992 is determined. This figure shows the octal value, the value of each digit, and the decimal result.

Figure 5.6. The year 1992 in decimal and octal.

145

Part I • Honing Your C Skills

Looking at a File

In any program that writes a file that is not pure text, you must able to look at the file and determine whether the program has written the file properly. When you run the DEBUG utility, a crude debugger, on the PC, it enables you to dump programs and data files. Because the program is difficult to use, however, it is not used often.

One solution is to have a program that dumps files and provides both a hex and ASCII listing of the file’s contents (see Listing 5.1,). DUMP is a simple program that reads files of any length and lists their contents in an easy-to-use format.

Listing 5.1. DUMP.C.

/* DUMP, written 23 May 1992 by Peter D. Hipson */ /* A program that dumps files in hex and ASCII. */

#include

 

<stdio.h>

// Make includes first part of file

#include

 

<string.h>

// For string functions.

#include

 

<stdlib.h>

// Standard include items.

#include

 

<process.h>

// For exit(), etc.

#include

 

<time.h>

// For time information.

#define

 

ARG_HELP

‘?’

#define

 

ARG_SLASH

‘/’

#define

 

ARG_DASH

‘-’

int main(

 

// Define main() and the fact that

int

 

argc,

// this program uses the passed parameters.

char

 

*argv[],

 

char

 

*envp[]

 

);

 

 

 

int main(

 

 

int argc,

 

char

 

*argv[],

 

char

 

*envp[])

 

{

 

 

 

FILE

*fpFilePointer;

146

Decimal, Binary, Hex, and Octal

long

lPosition;

int

i;

int

j;

int

nNumberBytesRead;

unsigned

int nHexNumber;

char

*pszTemp;

/* strings for _splitpath() (which parses a file name) */

char

szDrive[_MAX_DRIVE];

char

szDir[_MAX_DIR];

char

szFname[_MAX_FNAME];

char

szExt[_MAX_EXT];

char

szInputFile[128];

char

szProgram[132];

char

szBuffer[132];

char

sBuffer[257];

time_t

tTime;

struct

tm *pTM;

_splitpath(argv[0], szDrive,

szDir,

szFname,

szExt);

strncpy(szProgram, szFname, sizeof(szProgram) - 1);

if (argc <= 1)

{

printf(“%s: - No file name given.\n”, szProgram); exit(4);

}

for (i = 1; argv[i]; i++)

{

C C C

C5C C

C C C

continues

147

Part I • Honing Your C Skills

Listing 5.1. continued

if (argv[i][0] == ‘/’ || argv[i][0] == ‘-’)

{/* You have an argument, convert to lowercase, and test. */ pszTemp = strlwr(argv[i]);

for (j = 1; j < strlen(pszTemp); j++)

{

switch(pszTemp[j])

{

case ARG_HELP:

printf(“Usage: %s filename.ext \n”, szProgram);

exit(4);

break;

case ARG_SLASH: case ARG_DASH: break;

default:

printf(“%s: - Invalid option ‘%c’.\n”, pszTemp[j],

szProgram);

break;

}

}

}

else

{/* Either a filename or width. */ strcpy(szInputFile, argv[i]);

}

}

if ((fpFilePointer = fopen(szInputFile, “r+b”)) == NULL)

{

printf(“%s: Unable to open file: %s\n”, szProgram,

szInputFile);

148

Decimal, Binary, Hex, and Octal

exit(16);

}

lPosition = 0l;

printf(“\n”);

time(&tTime);

pTM = localtime(&tTime);

/* format a time string, using strftime() (new with ANSI C) */

strftime(szBuffer,

sizeof(szBuffer),

“%A %B %d, %Y at %H:%M:%S”, pTM);

printf(“Dump of %s, %s\n\n”, szInputFile,

szBuffer);

while((nNumberBytesRead = fread((char *)sBuffer, sizeof(char), 16, fpFilePointer)) > 0)

{

printf(“ %8.8X -”, lPosition);

for (i = 0; i < 16; i++)

{

if (i == 8)

{

printf(“ - “);

}

else

{

if (i ==

0

||

i ==

4

||

i ==

12)

{

 

 

C C C

C5C C

C C C

continues

149

Part I • Honing Your C Skills

Listing 5.1. continued

printf(“ “);

}

}

if (i < nNumberBytesRead)

{

nHexNumber = (unsigned char)sBuffer[i];

printf(“%2.2X”, (unsigned int)nHexNumber);

}

else

{

printf(“ “);

}

}

for (i = 0; i < nNumberBytesRead; i++)

{

if (sBuffer[i] < ‘ ‘ || sBuffer[i] == ‘\xFF’)

{

sBuffer[i] = ‘.’;

}

}

sBuffer[nNumberBytesRead] = ‘\0’;

printf(“ : %s”, sBuffer);

printf(“ \n”); lPosition += 16;

}

return(0);

}

150

Decimal, Binary, Hex, and Octal

C C C

 

C5C

 

C C C

 

C

DUMP.C has few unusual parts. The first part of the program is the same command line arguments parser from Chapter 4, “Special Pointers and Their Use,” with a test for the help option (standardized as /? under DOS on the PC). DUMP has no other options and simply requires the name of the file to dump.

The file is opened and read in 16 bytes at a time (or less, if fewer than 16 bytes remain in the file). The buffer, with 16 bytes, is written out, first in hex format and then in ASCII format (with control characters, and a . character substituted for DEL.

DUMP enables you to look at a file’s output; you still must understand what the output means, however.

There are two ways to store integers in memory. The first method, in which the high-order bits are stored in the low byte or bytes, makes dumps easy to read; in the second method, the low-order bits are stored in the low byte or bytes. One method makes it easier for you to look at a dump and determine an integer’s value, and the other method makes you work a little harder. The PC, of course, makes you work harder; supposedly, it makes the CPU faster, but we’ll never know. Figure 5.7 shows both a 16-bit integer and a 32-bit integer, as they are stored in the PC’s format.

Figure 5.7. Integers in memory (16 and 32 bits).

The method your CPU uses to store integers must always be considered whenever you are viewing memory directly. If you do not know the order of the bits in storage, the simple program in Listing 5.2 tells you which method is being used.

151

Part I • Honing Your C Skills

Listing 5.2. WCHBYTE.C.

/* Program WCHBYTE, written 25 May 1992 by Peter D. Hipson */ /* Program that shows byte swapping (if present) by the CPU. */

#include

<stdio.h>

// Make includes first part of file

#include

<string.h>

// For string functions.

#include

<stdlib.h>

// Standard include items.

#include

<process.h> // For exit() etc.

int main(

 

// Define main() and the fact that this program uses

int

argc,

// the passed parameters.

char

*argv[],

 

 

char

*envp[]

 

 

);

 

 

 

void NonPrint(const char

chChar);

void Letter(const char

chChar);

void Number(const char

chChar);

void Space(const char

chChar);

int main(

 

 

 

int

argc,

 

 

char

*argv[],

 

 

char

*envp[]

 

 

)

 

 

 

{

unsigned char cTemp[10]; unsigned char *pcTemp;

int

nYear = 1992;

long int lYearYear = 19921992;

char

szHello[] = “Hello”;

pcTemp = (unsigned char *)&nYear; cTemp[0] = *(pcTemp++);

cTemp[1] = *(pcTemp);

152

Decimal, Binary, Hex, and Octal

C C C

 

C5C

 

C C C

 

C

printf(“nYear = %d decimal, %4.4X hex, in memory %2.2X %2.2X\n”, nYear,

nYear,

cTemp[0],

cTemp[1]);

pcTemp = (unsigned char *)&lYearYear; cTemp[0] = *(pcTemp++);

cTemp[1] = *(pcTemp++); cTemp[2] = *(pcTemp++); cTemp[3] = *(pcTemp);

printf(“lYearYear = %ld decimal %8.8lX hex, in memory %2.2X %2.2X \ %2.2X %2.2X\n”,

lYearYear,

lYearYear,

cTemp[0],

cTemp[1],

cTemp[2],

cTemp[3]);

pcTemp = (unsigned char *)&szHello[0]; cTemp[0] = *(pcTemp++); // H

cTemp[1] = *(pcTemp++); // e cTemp[2] = *(pcTemp++); // l cTemp[3] = *(pcTemp++); // l cTemp[4] = *(pcTemp++); // o cTemp[5] = *(pcTemp++); // \0 (NULL)

printf(“szHello = ‘%s’ (string), in memory ‘%c’ ‘%c’ ‘%c’ ‘%c’ ‘%c’ \ ‘%c’ \n”,

szHello,

cTemp[0],

cTemp[1],

cTemp[2],

cTemp[3],

cTemp[4],

cTemp[5]);

return(0);

}

153

Part I • Honing Your C Skills

If the hex representation and the memory view of the variables are the same when you run WCHBYTE, dumps made using DUMP will be correct. If they are different, however (which is the case for all PCs), you have to swap the bytes manually when you are using a DUMP listing.

Bit Operators

Bit operators form the basis for C’s powerful bit-manipulation capabilities. Never confuse these operators with their logical counterparts, which work on different principles. In Table 5.1, the keyword TRUE signifies a true bit (or bits) that is set to one, and FALSE signifies a bit (or bits) that is set to zero.

Table 5.1. Bitwise operators.

Operator Description

&Performs a bitwise AND operation. If both operands are TRUE, the result is TRUE; otherwise, the result is FALSE.

|

Performs a bitwise OR operation. If either operand is TRUE, the

 

result is TRUE; otherwise, the result is FALSE.

^Performs a bitwise exclusive OR operation. If both operands are TRUE or both operands are FALSE, the result is FALSE. The result is TRUE if one operand is TRUE and the other is FALSE. Exclusive OR is

used to test to see that two operands are different.

<<Shifts the X operand, Y operand bits to the left. For example, (1 << 4) returns a value of 8. In bits, (0001 << 4) results in 1000. New positions to the left are filled with zeroes. This is a quick way to multiply by 2, 4, 8, and so on.

>>Shifts the X operand, Y operand bits to the right. For example, (8 >> 4) returns a value of 1. In bits, (1000 >> 4) results in 0001. New positions to the right are filled with ones or zeroes, depending on the value and whether the operand being shifted is signed. This is a quick way to divide by 2, 4, 8, and so on.

~Returns the 1’s complement of the value. The 1’s complement is defined as setting all bits that are 1 to 0, and all bits that are 0 to 1.

154