Sunday, December 6, 2009

Device Code Page Modes

You can use the mode command to set or display code pages for parallel printers or your console screen device. You can use the following options with mode to set or display code pages:

device Specifies the device to support code page switching. Valid device names are con, lptl, lpt2, and lpt3.

yyy Specifies a code page. Valid pages are 437, 850, 860, 863, and 865.

filename Identifies the name of the code page information (.cpi) file DOS should use to prepare a code page for the device specified.



There are four keywords that you can use with the mode device codepage command. Each causes the mode command to perform a different function. The following explains each keyword:

prepare Tells DOS to prepare code pages for a given device. You must prepare a code page for a device before you can use it with that device.

select Specifies which code page you want to use with a device. You must prepare a code page before you can select it.

refresh If the prepared code pages for a device are lost due to hardware or other errors, this keyword reinstates the prepared code pages.

/status Displays the current code pages prepared and/or selected for a device. Note that both these commands produce the same results:



mode con codepage

mode con codepage /status

Note

Suppose you want your computer to send its printer output to a serial printer. To do this, you need to use the mode command twice. The first mode command specifies the asynchronous communication

209

You can use the following abbreviations with the mode command for code page modes:

modes; the second mode command redirects the computer's parallel printer output to the asynchronous communication port specified in the first mode command.



For example, if your serial printer operates at 4800 baud with even parity, and if it is connected to the COM1 port, type:



mode coml:48,e,,,p mode lpt1:=com1:



If you want your computer to print on a parallel printer that is connected to your computer's second parallel printer port (LPT2), and you want to print with 80 characters per line and 8 characters per inch, type:

mode lpt2: 8 0,8 or

mode lpt2:,8 More

More sends output to the console one screen at a time.

Syntax

more ) character

$l


The less-than (<) character

$b


The pipe (|) character

$_


Return-Linefeed

$e


ASCII code X'1B' (escape)

$h Backspace

Example

The following command sets a two-line prompt that displays the current date and time:

prompt time = $t$_date = $d Recover

This command recovers a file or disk that contains bad sectors.

Syntax

recover [drive:][path]filename or

recover [drive:]

Comments:

If the chkdsk command shows that a sector on your disk is bad, you can use the recover command to recover the entire disk or just the file containing the bad sector. The recover command causes DOS to read the file, sector by sector, and to skip the bad sectors.

Examples

To recover a disk in drive A, type:

recover a:



Suppose you have a file named sales.jan that has a few bad sectors. To recover this file, type:

recover sales.jan Ren (Rename)

Rename changes the name of a file.

Syntax

rename [drive:][path]filename1 filename2 ren [drive:][path]filename1 filename2

Where: filename1 is the old name, and filename2 is the new name.

Examples

The following command changes the extension of all filenames ending in .txt to .doc:

ren *.txt *.doc

The following command changes the file one.jan (on drive B) to two.jan:

ren b:one.jan two.jan

Replace

Replace updates previous versions of files.

Syntax

replace [drive:]pathname1 [drive:][pathname2] [/a][/p][/r][/s][/w] Where pathname1 is the source path, and filename pathname2 is the target path and filename.

Comment



The replace command accepts the following switches:



/a Adds new files to the target directory instead of replacing existing ones.



/p Prompts you with the following message before it replaces a target file or adds a source file: ''Replace filename?(Y/N)"

/r Replaces read-only files as well as unprotected files.

/s Searches all subdirectories of the target directory while it replaces matching files.

/w Waits for you to insert a disk before beginning to search for source files. Example

Suppose various directories on your hard disk (drive C) contain a file named phone.cli that contains client names and numbers. To update these files and replace them with the latest version of the phone.cli file on the disk in drive A, type:

replace a:\ phone.cli c:\ /s

Restore

This command restores files that were backed up using the backup command.

Syntax

restore drive1:[drive2:][pathname] [/s][/p][/b:date][/a:date]

[/e:time][/L:time][/m] [/n] Where drive1 contains the backed-up files, and drive2 is the target drive.

Comment

The restore command accepts the following switches:
/s Restores subdirectories also.

/p Prompts for permission to restore files.

/b:date Restores only those files last modified on/or before date.

/a:date Restores only those files last modified or/or after date.

/e:time Restores only those files last modified at/or earlier than time.

/L:time Restores only those files last modified at/or later than time.

/m Restores only those files modified since the last backup.

/n Restores only those files that no longer exist on the target disk.



Example

To restore the file report.one from the backup disk in drive A to the \sales directory on drive C, type: restore a: c:\sales\report.one Rmdir (Rd)

Rmdir removes a directory from a multilevel directory structure. Syntax

rmdir [drive:]path or

rd [drive:]path Comments

Rmdir removes a directory that is empty, except for the "." and symbols. These two symbols refer to the directory itself and its parent directory. Before you can remove a directory entirely, you must delete its files and subdirectories.



Note

You cannot remove a directory that contains hidden files.

Example

To remove a directory named \papers\jan, type:

rd \papers\jan

Select



Select installs DOS on a new floppy with the desired country-specific information and keyboard layout.



Syntax

select[[drive1:] [drive2:][path]] [yyy][xx] Where drive1 is the source drive, and drive2 is the target drive. Comments

The select command lets you install DOS on a new disk along with country-specific information (such as date and time formats and collating sequence) for a selected country. The select command does the following:

Formats the target disk.

Creates both the config.sysand autoexec.bat files on a new disk.

Copies the contents of the source disk, track by track, to the target disk.



The source drive may be either drive A or B. The default source drive is A, and the default target drive is B. You can use the following options with the select command:



yyy Specifies the country code.

xx Specifies the keyboard code for the keyboard layout used (see the keyb command). Example

Suppose you want to create a new DOS disk that included the country-specific information and keyboard layout for Germany. With your source disk in drive B and your target disk in drive A, type:



select b: a: 049 gr



Set



This command sets one string of characters in the environment equal to another string for later use in programs.

Syntax

set [string = [string]] Comments

You should use the set command only if you want to set values for programs you have written. When DOS recognizes a set command, it inserts the given string and its equivalent into a part of memory reserved for the environment. If the string already exists in the environment, it is replaced with the new setting.



If you specify just the first string, set removes any previous setting of that string from the environment. Or, if you use the set command without options, DOS displays the current environment settings.



Example



The following command sets the string "hello" to c:\letter until you change it with another set command: set hello=c:\letter Share

Share installs file sharing and locking.

Syntax:

share [/f:space][/L:locks] Comments

You can see the share command only when networking is active. If you want to install shared files, you can include the share command in your autoexec.bat file.



The share command accepts the following switches:

/f:space Allocates file space (in bytes) for the DOS storage area used to record file-sharing information. The default value is 2048. Note that each open file requires enough space for the length of the full filename, plus 11 bytes, since an average pathname is 20 bytes in length.

/L:locks Allocates the number of locks you want to allow. The default value is 20.

Example

The following example loads file sharing, and uses the default values for the /f and /L switches:

share



Sort



Sort reads input, sorts the data, then writes the sorted data to your screen, to a file, or to another device.



Syntax

[source] | sort [/r][/+n] or

sort [/r] [/+n] source



Where source is a filename or command.



Comment



The sort command is a filter program that lets you alphabetize a file according to the character in a certain column. The sort program uses the collating sequence table, based on the country code and code page settings.



The pipe (|) and less-than (<) redirection symbols direct data through the sort utility from source. For example, you may use the dir command or a filename as a source. You may use the more command or a filename as a destination.

The sort command accepts the following switches:

/r Reverses the sort; that is, sorts from Z to A and then from 9 to 0.

/+n Sorts the file according to the character in column n, where n is some number.



Unless you specify a source, sort acts as a filter and accepts input from the DOS standard input (usually from the keyboard, from a pipe, or redirected from a file).



Example



The following command reads the file expenses.txt, sorts it in reverse order, and displays it on your screen:

sort /r expenses.txt Subst

This command substitutes a path with a drive letter.

Syntax

subst [drive: drive:path] or

subst drive: /d

Comments

The subst command lets you associate a path with a drive letter. This drive letter then represents a virtual drive because you can use the drive letter in commands as if it represented an actual physical drive.



When DOS finds a command that uses a virtual drive, it replaces the drive letter with the path, and treats that new drive letter as though it belonged to a physical drive.



If you type the subst command without options, DOS displays the names of the virtual drives in effect.

You can use the /d switch to delete a virtual drive.

Example

The following command creates a virtual drive, drive Z, for the pathname b:\paper\jan\one:

subst z: b:\paper\jan\one Sys

Sys transfers the DOS system files from the disk in the default drive to the disk in the specified drive.

Syntax

sys drive: Comment

The sys command does not transfer the command.com file. You must do this manually using the copy command.



Example

If you want to copy the DOS system files from your working directory to a disk in drive A, type:

sys a:

Time

This command allows you to enter or change the time setting.

Syntax

time [hours:minutes[:seconds [.hundredths]]] Comment

DOS typically keeps track of time in a 24-hour format.

Tree



Tree displays the path (and, optionally, lists the contents) of each directory and subdirectory on the given drive.

Syntax

tree [drive:] [/f]

Example

If you want to see names of all directories and subdirectories on your computer, type: tree

Comment

The /f switch displays the names of the files in each directory. Type

Type displays the contents of a text file on the screen. Syntax

type [drive:]filename



Example

If you want to display the contents of a file called letter.bob, type:



type letter.bob



If the contents of the file are more than a screen long, see the more command on how to display screen by screen.



Ver

Ver prints the DOS version number. Syntax

ver

Example

If you want to display the DOS version on your system, type: ver

Verify



This command turns the verify switch on or off when writing to a disk.



Syntax

verify [on] or

verify [off]



Comments



You can use this command to verify that your files are written correctly to the disk (no bad sectors, for example). DOS verifies the data as it is written to a disk.



Vol



Vol displays the disk volume label, if it exists.

Syntax

vol [drive:] Example

If you want to find out what the volume label is for the disk in drive A, type:



vol a:



Xcopy

Xcopy copies files and directories, including lower-level directories, if they exist. Syntax

xcopy [drive:]pathname[drive:][pathname][/a][/d:date] [/e][/m][/p][/s][/v][/w]



or



xcopy drive:[pathname][drive:][pathname][/a][/d:date] [/e][/m][/p][/s][/v][/w]



Comments



The first set of drive and pathname parameters specify the source file or directory that you want to copy; the second set names the target. You must include at least one of the source parameters. If you omit the target parameters, xcopy assumes you want to copy the files to the default directory.



The xcopy command accepts the following switches:

/a Copies source files that have their archive bit set.

/d:date Copies source files modified on or after the specified date.

/e Copies any subdirectories, even if they are empty. You must use this with the /s switch.

/m Same as the /a switch, but after copying a file, it turns off the archive bit in the source

file.



/p Prompts you with ''(Y/N)," allowing you to confirm whether you want to create each

target file.

/s Copies directories and lower-level subdirectories, unless they are empty.

/v Causes xcopy to verify each file as it is written.

/w Causes xcopy to wait before it starts copying files.



Example



The following example copies all the files and subdirectories (including any empty subdirectories) on the disk in drive A to the disk in drive B:

/ xcopy a: b: s /e Looking Ahead



Hackers consider the topics covered in this chapter to be vital ingredients for a solid technology core. Most also include programming languages such as C, Visual Basic, and Assembler to this list. The next chapter introduces the most prominent of these languages, the C language, in a dated fashion to help identify with the majority of security exploits and hacking tools employed throughout the Underground.



Hacker Coding Fundamentals The C Programming Language



All hackers, from the veteran to the novice, make learning the C language a mandatory part of their technical foundation because the majority of security exploits and hacking tools are compiled in the C programming language. Logically, then, most of the program code found throughout this book is a compilation of C source code extractions. These programs can be manipulated, modified, and compiled for your own custom analyses.



Hackers This section was written, with input from the programming guru, Matthew Probert, Mat*?'* as an introduction guide to the C programming language. Its purpose is to help fortify the programming foundation required to successfully utilize the code snippets found in this book and on the accompanying CD. For a complete jump-start course in C, take a look at the numerous John Wiley & Sons, Inc. publications at www.wiley.com.



The notable distinguishing features of the C programming language are:

Block-structured flow-control constructs (typical of most high-level languages)

Freedom to manipulate basic machine objects (e.g., bytes) and to refer to them using any particular object view desired (typical of assembly languages)

Both high-level operations (e.g., floating-point arithmetic) and low-level operations (which map closely onto machine-language instructions, thereby offering the means to code in an optimal, yet portable, manner)



This chapter sets out to describe the C programming language as commonly found with compilers for the PC, to enable a programmer with no extensive knowledge of C to begin programming in C using the PC (including the ROM facilities provided by the PC and facilities provided by DOS).



It is assumed that the reader has access to a C compiler, and to the documentation that accompanies it regarding library functions. The example programs were written with Borland's Turbo C; most of the nonstandard facilities provided by Turbo C can be found in later releases of Microsoft C.



Versions of C



The original C (prior to the publication of The C Programming Language (Prentice-Hall, 1988), by Kernighan and Ritchie) defined the combination assignment operators (+=, *=, etc.) backward (that is, they were written =+, =*, etc.). This caused terrible confusion when a statement such as:



x=-y;



was compiled. It could have meant:

Ritchie soon spotted this ambiguity and changed the language so that these operators were written in the now familiar manner (+=, *=, etc.). The major variations, however, are found between Kernighan's and Ritchie's C and ANSI C. These can be summarized as follows:

Introduction of function prototypes in declarations; change of function definition preamble to match the style of prototypes.

Introduction of the ellipsis (... ) to show variable-length function argument lists.

Introduction of the keyword void (for functions not returning a value) and the type void * for generic pointer variables.

Addition of string-merging, token-pasting, and string-izing functions in the preprocessor.

Addition of trigraph translation in the preprocessor.

Addition of the #pragma directive, and formalization of the declared( ) pseudofunction in the preprocessor.

Introduction of multibyte strings and characters to support non-English languages.

Introduction of the signed keyword (to complement the unsigned keyword when used in integer declarations) and the unary plus (+) operator.



Classifying the C Language



The powerful facilities offered by C that allow manipulation of direct memory addresses and data, along with C's structured approach to programming, are the reasons C is classified as a "medium-level" programming language. It possesses fewer ready-made facilities than a high-level language, such as BASIC, but a higher level of structure than the lower-level Assembler.



Keywords



The original C language provided 27 key words. To those 27, the ANSI standards committee on C added five more. This results in two standards for the C language; however, the ANSI standard has taken over from the old Kernighan and Ritchie standard. The keywords are as follows:



Auto


double


int


Struct

break


else


long


switch

Case


enum


register


Typedef

Char


extern


return


Union

Const


float


short


Unsigned

continue


for


signed


Void

Default


goto


sizeof


Volatile

Do


if


static


While



Note that some C compilers offer additional keywords, specific to the hardware environment on which they operate. You should be aware of your own C compiler's additional keywords.

Structure of C



C programs are written in a structured manner. A collection of code blocks are created that call each other to comprise the complete program. As a structured language, C provides various looping and testing commands, such as:



do-while, for, while, if



A C code block is contained within a pair of curly braces ({ } ), and may be a complete procedure called a function, or a subset of code within a function. For example, the following is a code block:



if (x < 10) {

a = 1; b = 0;

}



The statements within the curly braces are executed only upon satisfaction of the condition that x < 10.



This next example is a complete function code block, containing a subcode block as a do-while loop:



int GET_X()

{

int x;



do {

a number between 0 and 10 ");

printf ("\nEnter scanf("%d",&x);

}

10);

while(x < 0 || x > return(x);

}



Notice that every statement line is terminated in a semicolon, unless that statement marks the start of a code block, in which case it is followed by a curly brace. C is a case-sensitive, but free-flowing language; spaces between commands are ignored, therefore the semicolon delimiter is required to mark the end of the command line. As a result of its free-flow structure, the following commands are recognized as the same by the C compiler:



x = 0;

x =0; x=0;



The general form of a C program is as follows:

Compiler preprocessor statements

Global data declarations

Return-type main (parameter list)



{

statements return-type f1(parameter list) {

statements

}

return-type f2(parameter list)

{

statements









return-type fn(parameter list)

{

statements

}



Comments



As with most other languages, C allows comments to be included in the program. A comment line is enclosed within /* and */:

/* This is a legitimate C comment line */ Libraries



C programs are compiled and combined with library functions provided with the C compiler. These libraries are composed of standard functions, the functionalities of which are defined in the ANSI standard of the C language; they are provided by the individual C compiler manufacturers to be machine-dependent. Thus, the standard library function printf ( ) provides the same facilities on a DEC VAX as on an IBM PC, although the actual machine language code in the library is quite different for each. The C programmer, however, does not need to know about the internals of the libraries, only that each library function will behave in the same way on any computer.



C Compilation



Before we reference C functions, commands, sequences, and advanced coding, we'll take a look at actual program compilation steps. Compiling C programs are relatively easy, but they are distinctive to specific compilers. Menu-driven compilers, for example, allow you to compile, build, and execute programs in one keystroke. For all practical purposes, we'll examine these processes from a terminal console.

From any editor, enter in the following snippet and save the file as example.c: /*

simple pop-up text message

*/

#include void main()

{

printf( "Wassup!!\n" );

}

At this point, we need to compile our code into a program file, before the snippet can be run, or executed. At a console prompt, in the same directory as our newly created example.c, we enter the following compilation command:



cc example.c



Note that compilation command syntax varies from compiler to compiler. Our example is based on the C standard. Currently, common syntax is typically derived from the GNU C compiler, and would be executed as follows:



gcc example.c



After successful completion, our sample snippet has been compiled into a system program file and awaits execution. The output, obviously deduced from the simple code, produces the following result:



Wassup!!

Press any key to continue



That's all there is to it! C snippet compilation is relatively easy; however, be aware of the results of destructive penetration programs. Of course, the exploit coding found throughout this book and available on the accompanying CD is much more complicated, but you get the idea.



Data Types



There are four basic types of data in the C language: character, integer, floating point, and valueless, which are referred to by the C keywords: char, int, float, and void, respectively. Basic data types may be added with the following type modifiers: signed, unsigned, long, and short, to produce further data types. By default, data types are assumed signed; therefore, the signed modifier is rarely used, unless to override a compiler switch defaulting a data type to unsigned. The size of each data type varies from one hardware platform to another, but the narrowest range of values that can be held is described in the ANSI standard, given in Table 7.1.



In practice, this means that the data type char is particularly suitable for storing flag type variables, such as status codes, which have a limited range of values. The int data type can be used, but if the range of values does not exceed 127 (or 255 for an unsigned char), then each declared variable would be wasting storage space.



Which real number data type to use—float, double, or long double—is a tricky question. When numeric accuracy is required, for example in an accounting application, instinct would be to use the long double, but this requires at least 10 bytes of storage space for each variable. Real numbers are not as precise as integers, so perhaps integer data types should be used instead, and work around the problem. The data type float is worse, since its six-digit precision is too inaccurate to be relied upon. Generally, you should use integer data types wherever possible, but if real numbers are required, then use a double.

Table 7.1 C Data Type Sizes and Ranges
TYPE SIZE RANGE

Char 8 - 127 to 127



unsigned char 8 0 to 255

Int


16


-32767 to 32767

unsigned int


16


0 to 65535

long int


32


-2147483647 to 2147483647

unsigned long int


32


0 to 4294967295

Float


32


6-digit precision

Double


64


10-digit precision

long double


80


10-digit precision





Declaring a Variable



All variables in a C program must be declared before they can be used. The general form of a variable definition is:



type name;



So, for example, to declare a variable x, of data type int so that it may store a value in the range -32767 to 32767, you use the statement:



int x;



Character strings may also be declared as arrays of characters:



char name[number_of_elements];



To declare a string called name that is 30 characters in length, you would use the following declaration:



char name[30];



Arrays of other data types may be declared in one, two, or more dimensions as well. For example, to declare a two-dimensional array of integers, you would use:



int x[10][10];



The elements of this array are accessed as:



x[0][0] x[0][1] x[n][n]



There are three levels of access to variables; local, module, and global. A variable declared within a code block is known only to the statements within that code block. A variable declared outside any function code blocks, but prefixed with the storage modifier ''static," is known only to the statements within that source module. A variable declared outside any functions, and not prefixed with the static storage type modifier, may be accessed by any statement within any source module of the program. For example: main()

{

int x; int y;







}



funca()

{

/* Test variable 'a' for equality with 0 */

if (a == 0)

{

int b;

for(b = 0; b < 20; b++)

printf ("\nHello World");

}



}

In this example the variable error is accessible by all source code modules compiled together to form the finished program. The variable a is accessible by statements in both functions main( ) and funca( ), but is invisible to any other source module. Variables x and y are accessible only by statements within function main( ). Finally, the variable b is accessible only by statements within the code block following the if statement.

If a second source module wanted to access the variable error, it would need to declare error as an extern global variable, such as:

extern int error; funcb()

{ }

C will readily allow you to assign different data types to each other. For example, you may declare a variable to be of type char, in which case a single byte of data will be allocated to store the variable. You can attempt to allocate larger values to this variable:

main()

{



x = 5000;



}



In this example, the variable x can only store a value between -127 and 128, so the figure 5000 will not be assigned to the variable x. Rather the value 136 will be assigned.



Often, you may wish to assign different data types to each other; and to prevent the compiler from warning of a possible error, you can use a cast statement to tell the compiler that you know what you're doing. A cast statement is a data type in parentheses preceding a variable or expression:



float x; int y;

x = 100 / 25; y = (int)x;

}



In this example the (int) cast tells the compiler to convert the value of the floating-point variable x to an integer before assigning it to the variable y.



Formal Parameters



A C function may receive parameters from a calling function. These parameters are declared as variables within the parentheses of the function name, such as:



int MULT(int x, int y)

{

/* Return parameter x multiplied by parameter y */ return(x * y);

}



main()

{

int a; int b; int c;



a = 5; b = 7;

c = MULT(a,b);



printf ("%d multiplied by %d equals %d\n",a,b,c);

}



Access Modifiers



There are two access modifiers: const and volatile. A variable declared to be const may not be changed by the program, whereas a variable declared as type volatile may be changed by the program. In addition, declaring a variable to be volatile prevents the C compiler from allocating the variable to a register, and reduces the optimization carried out on the variable.



Storage Class Types



C provides four storage types: extern, static, auto, and register. The extern storage type is used to allow a source module within a C program to access a variable declared in another source module. Static variables are accessible only within the code block that declared them; additionally, if the variable is local, rather than global, they retain their old value between subsequent calls to the code block.



Register variables are stored within CPU registers wherever possible, providing the fastest possible access to their values. The auto type variable is used only with local variables, and declares the

229

variable to retain its value locally. Since this is the default for local variables, the auto storage type is rarely used.



Operators



Operators are tokens that cause a computation to occur when applied to variables. C provides the following operators:



&


Address

*


Indirection

+


Unary plus

-


Unary minus

~


Bitwise complement

!


Logical negation

++


As a prefix; preincrement




As a suffix; postincrement

--


As a prefix; predecrement




As a suffix; postdecrement

+


Addition

-


Subtraction

*


Multiply

/


Divide

%


Remainder

<<


Shift left

>>


Shift right

&


Bitwise AND

|


Bitwise OR

A


Bitwise XOR

&&


Logical AND

||


Logical OR

=


Assignment

*=


Assign product

/=


Assign quotient

%= Assign remainder (modulus)

+= Assign sum

-= Assign difference

<<= Assign left shift

>>= Assign right shift

&= Assign bitwise AND

|= Assign bitwise OR

A= Assign bitwise XOR

< Less than

> Greater than

<= Less than or equal to

>= Greater than or equal to

== Equal to

!= Not equal to

. Direct component selector

-> Indirect component selector

a ? "If a is true, then x; else y"

x:y

[ ] Define arrays

( ) Parentheses isolate conditions and expressions.

... Ellipsis are used in formal parameter lists of function prototypes to show a variable number of parameters or parameters of varying types.



To illustrate some commonly used operators, consider the following short program:



main()

{

int a; int b;



int c;

a = 5; /*Assign a value of 5 to variable 'a'*/

b = a/2; /*Assign the value of 'a' divided by two to variable

'b'*/

c = b * 2; /*Assign the value of 'b' multiplied by two to variab

le

'c'*/



if (a == c) /* Test if 'a' holds the same value as 'c' */



puts("Variable 'a' is an even number"); else

puts("Variable 'a' is an odd number");



Normally, when incrementing the value of a variable, you would write something like:

x = x + 1

C also provides the incremental operator ++ so that you can write:

x++

Similarly, you can decrement the value of a variable using -- , as in: x--

All the other mathematical operators may be used the same; therefore, in a C program, you can write in shorthand:



NORMAL


C

x = x + 1


x++

x = x - 1


x--

x = x * 2


x *= 2

x = x / y


x /= y

x = x % 5


x %= 5



Functions



Functions are source code procedures that comprise a C program. They follow this general form:



return_type function_name(parameter_list) {

statements

}



The returntype specifies the data type that will be returned by the function: char, int, double, void, and so on. The code within a C function is invisible to any other C function; jumps may not be made from one function into the middle of another, although functions may call upon other functions. Also, functions cannot be defined within functions, only within source modules.



Parameters may be passed to a function either by value or by reference. If a parameter is passed by value, then only a copy of the current value of the parameter is passed to the function. A parameter passed by reference, however, is a pointer to the actual parameter, which may then be changed by the function. The following example passes two parameters by value to a function, funca( ), which attempts to change the value of the variables passed to it. It then passes the same two parameters by reference to funcb( ), which also attempts to modify their values:



#include



int funca(int x, int y)

{ /* This function receives two parameters by value, x and y */



x = x * 2; y = y * 2;



printf ("\nValue of x in funca() %d value of y in funca() %d",x,y

);



return(x);

}

int

{

funcb(int *x, int *y)

Подпись: /* This function receives two parameters by reference, x and y */

printf ("\nValue of x in funcb() %d value of y in funcb() %d",*x,

*y);



return(*x);

}

main() {

int x; int y;



int z;



x = 5; y = 7;

z = funca(x,y); z = funcb(&x,&y);



printf ("\nValue of x %d value of y %d value of z %d",x,y,z);

}



Here, funcb( ) does not change the values of the parameters it receives; rather, it changes the contents of the memory addresses pointed to by the received parameters. While funca( ) receives the values of variables x and y from function main( ), funcb( ) receives the memory addresses of the variables x and y from function main( ).

Passing an Array to a Function

The following program passes an array to a function, funca( ), which initializes the array elements:

#include

void funca(int x[])

{

int n;

for(n = 0; n < 100; n++) x[n] = n;

}



main()

{

int array[100]; int counter;



funca(array);



for(counter = 0; counter < 100; counter++)

printf ("\nValue of element %d is %d",counter,array[counter]);

}



The parameter of funca( ), int x[ ] is declared to be an array of any length. This works because the compiler passes the address of the start of the array parameter to the function, rather than the value of the individual elements. This does, of course, mean that the function can change the value of the array elements. To prevent a function from changing the values, you can specify the parameter as type const:



funca(const int x[])

{ }



This will generate a compiler error at the line that attempts to write a value to the array. However, specifying a parameter to be const does not protect the parameter from indirect assignment, as the following program illustrates:



#include



int funca(const int x[])

{

int *ptr; int n;



/* This line gives a 'suspicious pointer conversion warning' */ /* because x is a const pointer, and ptr is not */ ptr = x;



for(n = 0; n < 100; n++)

{

*ptr = n; ptr++;

}

}



main()

{

int array[100]; int counter;



funca(array);

for(counter = 0; counter < 100; counter++)

printf ("\nValue of element %d is %d",counter,array[counter]);

}



Passing Parameters to main()



C allows parameters to be passed from the operating system to the program when it starts executing through two parameters, argc and argv[ ], as follows:



#include



main(int argc, char *argv[])

{



int n;



for(n = 0; n < argc; n++)

printf ("\nParameter %d equals %s",n,argv[n]);

}



The parameter argc holds the number of parameters passed to the program; and the array argv[ ] holds the addresses of each parameter passed; argv[0] is always the program name. This feature may be put to good use in applications that need to access system files. Consider the following scenario: A simple database application stores its data in a single file called data.dat. The application needs to be created so that it may be stored in any directory on either a floppy diskette or a hard disk, and executed both from within the host directory and through a DOS search path. To work correctly, the application must always know where to find the data file data.dat. This can be solved by assuming that the data file will be in the same directory as the executable module, a not unreasonable restriction to place upon the operator. The following code fragment illustrates how an application may apply this algorithm to be always able to locate a desired system file:

#include

char system_file_name[160];

void main(int argc,char *argv[])

{

char *data_file = "DATA.DAT"; char *p;



strcpy(system_file_name,argv[0]);

p = strstr(system_file_name,".EXE");

if (p == NULL) ~~ ~~

{

/* The executable is a .COM file */ p = strstr(system_file_name,".COM");

}



/* Now back track to the last '\' character in the file name */ while(*(p - 1) != '\\') strcpy(p,data_file);





In practice, this code creates a string in systemjilename that is composed of path\data.dat. So if, for example, the executable file is called test.exe, and resides in the directory\borlandc, then systemjilename will be assigned with \borlandc\data.dat.



Returning from a Function



The return command is used to return immediately from a function. If the function is declared with a return data type, then return should be used with a parameter of the same data type.



Function Prototypes



Prototypes for functions allow the C compiler to check that the type of data being passed to and from functions is correct. This is very important to prevent data overflowing its allocated storage space into other variables' areas. A function prototype is placed at the beginning of the program, after any preprocessor commands, such as #include , and before the declaration of any functions.



C Preprocessor Commands



In C, commands to the compiler can be included in the source code. Called preprocessor commands, they are defined by the ANSI standard to be:

#if

#ifdef

#ifndef

#else

#elif

#endif

#include

#define

#undef

#line

#error

#pragma



All preprocessor commands start with a hash, or pound, symbol (#), and must be on a line on their own (although comments may follow). These commands are defined in turn in the following subsections.



#define



The #define command specifies an identifier and a string that the compiler will substitute every time it comes across the identifier within that source code module. For example:



#define FALSE 0

#define TRUE !FALSE



The compiler will replace any subsequent occurrence of FALSE with 0, and any subsequent occurrence of TRUE with !0. The substitution does not take place if the compiler finds that the identifier is enclosed by quotation marks; therefore:

would not be replaced, but

printf ("%d",FALSE); would be.

The #define command can also be used to define macros that may include parameters. The parameters are best enclosed in parentheses to ensure that correct substitution occurs. This example declares a macro, larger(),that accepts two parameters and returns the larger of the two:

#include

#define larger(a,b) (a > b) ? (a) : (b) int main()

{

printf ("\n%d is largest",larger(5,7));



}



#error



The #error command causes the compiler to stop compilation and display the text following the #error command. For example:



#error REACHED MODULE B

will cause the compiler to stop compilation and display:

REACHED MODULE B

#include

The #include command tells the compiler to read the contents of another source file. The name of the source file must be enclosed either by quotes or by angular brackets:



#include "module2.c" #include



Generally, if the filename is enclosed in angular brackets, the compiler will search for the file in a directory defined in the compiler's setup.



#if, #else, #elif, #endif



The #if set of commands provide conditional compilation around the general form:



#if constant_expression

statements #else

statements #endif

The #elif commands stands for #else if, and follows the form:



#if expression

statements #elif expression

statements endif



#ifdef, #ifndef



These two commands stand for #if defined and #if not defined, respectively, and follow the general form:



#ifdef macro_name

statements #else

statements #endif



#ifndef macro_name

statements #else

statements #endif

where macroname is an identifier declared by a #define statement. #undef

The #undef command undefines a macro previously defined by #define.

#line



The #line command changes the compiler-declared global variables LINE and FILE . The

general form of #line is:



#line number "filename"



where number is inserted into the variable LINE and ''filename" is assigned to FILE .



#pragma

This command is used to give compiler-specific commands to the compiler. Program Control Statements



As with any computer language, C includes statements that test the outcome of an expression. The outcome of the test is either TRUE or FALSE. C defines a value of TRUE as nonzero, and FALSE as zero.



Selection Statements



The general-purpose selection statement is "if," which follows the general form:

if (expression)

statement else

statement



where statement may be a single statement or a code block enclosed in curly braces (the else is optional). If the result of the expression equates to TRUE, then the statement(s) following the if( ) will be evaluated. Otherwise the statement(s) following the else will be evaluated.



An alternative to the if.. .else combination is the ?: command, which takes the following form:



expression ? true_expression : false_expression



If the expression evaluates to TRUE, then the trueexpression will be evaluated; otherwise, the falseexpression will be evaluated. In this case, we get:



#include



main()

{

int x; x = 6;

printf ("\nx is an %s number", x % 2 == 0 ? "even" : "odd");

}



C also provides a multiple-branch selection statement, switch, which successively tests a value of an expression against a list of values, then branches program execution to the first match found. The general form of switch is:



switch (expression)

{

case valuel : statements break; statements break;









case valuen : statements

break; default : statements

}



The break statement is optional, but if omitted, program execution will continue down the list.

#include main()

{

int x;

switch (x)

printf


(" \nx


equals


zero");

printf


(" \nx


equals


one");

printf


(" \nx


equals


two");

printf


(" \nx


equals


three");

{

case 0 : break; case 1 : break; case 2 :

break; case 3 break;

default : printf ("\nx is larger than three");

}

}



Switch statements may be nested within one another.

No comments:

Post a Comment