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

Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)

.pdf
Скачиваний:
192
Добавлен:
12.08.2013
Размер:
3.18 Mб
Скачать

1 GETTING STARTED 11

What we have described so far is the most general case for a function. This is shown schematically in Figure 1-4. There are a number of special cases. These special cases depend on whether or not the function receives parameters and whether or not it returns a value. The number of parameters received by a function can vary from function to function.

The number of values returned by a function is always one and it must be a scalar quantity. A scalar quantity can be loosely defined as a single entity. In other words, functions cannot return arrays (groups of entities). For example, a function can produce a result through the return value, which is just one integer. It cannot produce a result that has more than one integer. Figure 1-5 and Figure 1-6 show some typical forms of functions.

 

Because the return

 

value type is void,

a

NO value is returned

 

void func1(int a, int b)

b

The two integers a and b are the two inputs to the function

Figure 1-5 A function that takes two arguments and returns NO value.

For the case shown in Figure 1-5 the function will perform a task such as calculate a value and print a message on the screen. If that is all the function needs to do, then there is no need for the function to return a value.

int func2(void)

No parameters are

taken by the function

An integer value is returned by the function

Figure 1-6 A function that takes no parameters but returns a value.

In the case of Figure 1-6, the function may be receiving some data from an external source such as the printer port and returning an integer number. For example, the integer number may indicate the status of paper in the printer; 0 indicating no paper and 1 indicating paper is still present.

12 1 GETTING STARTED

1.4.1 A Program with a Function Call

The program shown in Listing 1-2 produces the same output as the program in Listing 1-1. The only difference is that it uses a function to produce the output on the screen. Moreover, the function does not receive any parameters and does not produce any return value. The main emphasis in this section is to explain the concept of procedure abstraction. Procedure abstraction means hiding the details of a certain procedure behind a function and then calling the function to have the procedure carried out.

Listing 1-2 A program with a function call.

/* This program prints a text message on your screen. The program consists of two functions named PrintMessage and main.*/

#include <iostream.h>

//The PrintMessage() function void PrintMessage()

{

cout << “Getting Started” << endl;

}

//The main function.

void main()

{

PrintMessage(); // calling the function

}

A new function named PrintMessage has been added to this program. The name PrintMessage is our own creation. We have also added the pair of parentheses at the end of the name PrintMessage to signify it as being a function. The pair of parentheses are empty (which is equivalent to placing void there) because the function does not have any parameters. The return value type of the PrintMessage() function is void because the function does not return any value. The definition of the PrintMessage() function is as follows:

void PrintMessage()

{

cout << “Getting Started” << endl;

}

A function definition must specify four things, being: 1. The return value type

1 GETTING STARTED 13

2.The function name

3.Number of parameters and their types

4.The body of the function

The syntax of a function is depicted in Figure 1-7:

Return value type

Number of parameters and their types

Function name

 

void PrintMessage()

{

cout << “Getting Started” << endl;

The body of the function

 

}

Figure 1-7 The syntax of a function definition.

The function definition contains the complete function, informing the compiler what instructions need to be executed. In other words, the body of the PrintMessage() function is provided, starting with the open brace and ending with the close brace. Note: a semicolon is not placed after the function name PrintMessage(). This allows the following lines containing the function body to be associated with the function name.

The return value type is void for the PrintMessage() function. The function name is PrintMessage. The list of parameters is empty and the body of the function contains the cout statement.

A function declaration is slightly different (as shown in Figure 1-8). It is sufficient for the compiler to just see the function declaration for it to be able to compile calls to the function. The entire function definition is not needed at this stage. However, in order to execute the function, a compiled version of the function definition is needed. The function declaration has to specify only three things:

1.The return value type.

2.The function name.

3.Number of parameters and their types.

Return value type

Number of parameters and their types

Function name

 

void PrintMessage();

Figure 1-8 Function declaration, also known as the function prototype.

14 1 GETTING STARTED

The body of the function is not necessary. However, it must be provided sometime before execution of your program. If the body of the function is obtained from a library, then it will be brought in at linking time. If it is not obtained from a library or another object file, then you must type the code for the function somewhere in your program. In our example, the function declaration would be:

void PrintMessage();

Note that the line ends with a semi-colon.

In C++, the function prototype is exactly the same as the function declaration. However, in a C program the function declaration and function prototype are two different things. See the note in Section 1.6 for an example.

In the main() function the body has been changed. The only statement in the body is:

PrintMessage();

Note that the line ends with a semi-colon and the return value type does not appear. Such a line is termed a function call. In a function call, two things must be specified. They are:

1.The function name.

2.The list of actual arguments.

Return value type is not mentioned

Function name

Formal arguments must be replaced

PrintMessage(); by actual arguments

Figure 1-9 An example showing the syntax of a function call.

The actual arguments replace the parameters (or the formal arguments) when it comes to the time of execution. Note the syntax and that the line ends with a semicolon. An example of a function call that uses a parameter list can be found in Section 1.6.

When the program is executed, as always its execution will begin at the main() function. Then the body of the main() function will be executed. At this time the computer will encounter the instruction:

PrintMessage();

This is a function call that results in the execution of the body of the PrintMessage() function. Therefore, the message Getting Started will be printed on your screen. As mentioned at the start of this section, using the PrintMessage() function in the main() function enables the details of what it does to be hidden - known as procedure abstraction (explained in Section 1.6).

1 GETTING STARTED 15

1.5 Fundamental Data Types

Most of the time programming instructions manipulate data. As such, data plays an important role in programs. Data comes in a variety of data types that is sometimes mixed in with other types. It is important to be able to identify data of different types. There are a small number of data types built into the C++ language known as fundamental data types. Data types are described by three attributes:

1.The name of the data type.

2.The size of the data type in bytes (see Chapter 2).

3.The range of values the data type can handle.

For C++ data types, the size (and therefore the range) differs depending on whether we write 16-bit programs or 32-bit programs. Bits and bytes are explained in the next chapter. For now, it is sufficient to know that 32-bit data types occupy more memory and cover values over a larger range than 16-bit data types.

Data types can be broadly categorised into three types:

1.Integral data types.

2.Floating point data types.

3.Pointer data types.

Integral data types are used to store integral type data (whole numbers) whereas floating-point data types store numbers with a fractional part. Pointer data types are used to store memory addresses. Memory addresses are described in Chapter 2 and pointer data types are discussed in Chapter 7.

The integral data types are further sub-divided into signed types and unsigned types. The signed types can carry both positive and negative numbers whereas unsigned types carry only positive numbers. Floating point numbers can carry both positive and negative numbers. The pointer data types are always positive since there are no negative memory locations.

A programmer can use these fundamental data types to develop custom data types that can be very complex. To start with we will be looking at the following three fundamental data types:

char int float

The first two are integral types and the third is a floating-point type. Table 1-1 shows the three data types mentioned above along with their sizes in bytes and the range of values they can take.

16 1 GETTING STARTED

Table 1-1 A few of the fundamental data types.

 

Number of

 

 

Data type

bytes

Range of values

char

1

-128 to 127

unsigned char

1

0 to 255

int

2

-32768 to 32767

unsigned int

2

0 to 65535

float

4

ρ3.4υ10-38

to ρ3.4υ1038

double

8

ρ1.7υ10-308

to ρ1.7υ10308

Data Type char

This is the data type that is primarily used to store characters. One char type data will occupy one byte in memory. The signed version is simply referred to as char and the unsigned version as unsigned char. This data type can also be used to store small integer numbers that fit into one byte of memory.

Data Type int

This is the data type that is used to store integer numbers. One int type data will occupy 2 bytes of memory in 16-bit programs. The signed version is simply referred to as int and the unsigned version as unsigned int. A synonym for int in 16-bit representation is short int.

Data Type float

This is the data type that is used to store fractional numbers. One float type data occupies 4 bytes in memory. The data type float can handle both positive and negative numbers and so there is no separate data type named unsigned float!

Identifiers

Identifiers are the symbols or variable names we will be using in our programs to identify various entities such as integers, floating point numbers, characters, memory addresses, functions, objects, classes and many more. Identifiers are case sensitive and can be of any length.

NOTE

Identifiers must start with a letter (upper case or lower case) or the underscore “_”

character. They may contain digits (0 to 9), but not as the first character of the identifier.

An identifier must be declared before using it in a program. When declaring an identifier you must specify two things (as shown in Figure 1-10):

1 GETTING STARTED 17

1.The data type

2.The identifier name

Data type

Identifier Name

int a; Semi-colon is a must!

Figure 1-10 An example showing the syntax of a single identifier declaration.

An example of an identifier declaration is:

int a;

The data type is int and the identifier name is a. If needed, more than one identifier can be declared in one statement as shown in Figure 1-11:

Data type

Identifiers, all of type int

int a,b,c;

Semi-colon is a must!

Commas used to separate identifiers

Figure 1-11 An example showing the syntax of a multiple identifier declaration.

Such a declaration must be provided before being able to use an identifier in your program.

An identifier can also be declared and initialised simultaneously. In such a case, in addition to declaring the variable, we also set the identifier to take up an initial value. An example of such a situation that applies to a single identifier is:

int a=0;

The data type is int, variable name is a and it is initialised to have a value of 0 as shown in Figure 1-12.

Data type

Identifier

Assigned value

int a=0;

Semi-colon is a must!

Equal sign is used to assign the initial value

Figure 1-12 An example - syntax of a single identifier declaration and definition.

18 1 GETTING STARTED

The identifier declarations we have seen so far can be combined in any manner. Such a declaration is shown in Figure 1-13:

Data type

Identifiers, all of type int

int a=0,b,c;

Semi-colon is a must!

Commas used to separate identifiers

This identifier is initialised to 0

Figure 1-13 An example showing the syntax of a general identifier declaration.

1.6 Functions with Parameters and Return Values

In Section 1.4.1 we learned how to make a function call with a view to understand the concept of procedure abstraction. In this section we will look at a function that can be called repeatedly to carry out the addition of two numbers. We will program the function to receive the two numbers as parameters and to return their sum as the end result produced by the function. This will help us understand the role of function parameters and their return value.

Listing 1-3 Functions with parameters and return values.

/* This program calls a function (twice) to add two numbers together from within the main function and outputs the result to the screen. */

#include <iostream.h>

float Add (float a, float b) // The Add() function

{

float sum;

sum = a + b; return sum;

}

void main()

// The main function.

{

 

float p=1, q=2.3, r=3, s=4.5;

1 GETTING STARTED 19

float Sum1, Sum2;

Sum1 = Add(p,q); // First call to ‘Add’ function cout << “First Sum “ << Sum1 << endl;

Sum2 = Add(r,s); // Second call to ‘Add’ function

cout << “Second Sum “ << Sum2 << endl;

}

In the program shown in Listing 1-3 we have defined a new function named Add. As mentioned earlier, the definition of a function provides the return value type, the function name, the list of parameters and their types, and the body of the function. Unlike the function we have seen so far in this book, the Add() function’s pair of parentheses are not empty, meaning the function receives some parameters. In this case the Add() function receives two parameters of type float. Furthermore, the return value type of the Add() function is float. This means the function must produce a return value of type float. The value to be returned must also be specified within the body of the function in a return statement. The Add() function is reproduced below to explain its operation:

float Add (float a, float b)

{

float sum;

sum = a + b; return sum;

}

NOTE

According to the C language, the declaration of the Add() function is:

float Add();

Therefore, a declaration in C does not provide information about the parameters.

The prototype of the Add() function is:

float Add(float, float);

This does provide information about the parameters. In C++, the declaration and

the prototype of a function are exactly the same. Therefore, the prototype (and

declaration) of the function Add() is:

float Add(float, float);

20 1 GETTING STARTED

Within the body of this function we have declared a float type identifier named sum. Then sum is assigned the result of adding a to b. Finally, the return statement sends the value of sum out of the function. Note that the type of the returned value, i.e. the type of sum (which is float), is the same as the return value type of the Add() function (specified on the first line).

The main() function of our program is shown ahead, with its function calls highlighted in bold typeface. In the first call to the Add() function, its parameters or formal arguments a and b are replaced by copies of the actual arguments p and q, which carry real values. The parameters a and b can be viewed as placeholders. In the second call to the Add() function, its parameters are replaced by copies of r and s.

void main()

{

float p=1, q=2.3, r=3, s=4.5; float Sum1, Sum2;

Sum1 = Add(p,q); // First call to ‘Add’ function cout << “First Sum “ << Sum1 << endl;

Sum2 = Add(r,s); // Second call to ‘Add’ function

cout << “Second Sum “ << Sum2 << endl;

}

The value returned by the first call to the Add() function is assigned to Sum1. Therefore, Sum1 becomes the summation of p and q. In our case, Sum1 will have the value of 3.3. Similarly, Sum2 will have the value of 7.5. Since the main() function is making the calls to the Add() function, the main() function becomes the caller and at the same time the recipient of any return values. In this case, the main() function’s body is also known as the calling environment. The other lines in the main function are identifier declarations and/or definitions, and the statement used to print the values of Sum1 and Sum2 on the screen.

Figure 1-14 shows an example of the sequences a program goes through. This complete program consists of a main() function and a number of other functions and data. The program starts from within the main() function where various other functions are called throughout its operation.

The main() function and all the other functions are stored in the so-called code area of program memory, and are generally not expected to change during the life of the program. The data is stored in the data area where its contents are expected to change. Apart from the data in fixed data areas, there may be other data that is created in a temporary area known as the stack, and also in a semi-permanent area known as the heap (or free store).