天天看点

Chapter 3 Functions and Pointers

Chapter 3 Functions and Pointers

?This chapter continues the discussion of the

C++ kernel language, focusing on functions,

pointers, and arrays.

3.1 Functions

?A problem in C++ can be decomposed into

subproblems, each of which can be either

coded directly or further decomposed. This

is the method of stepwise refinement.

?Some functions, are provided by libraries.

Others can be written by the programmer.

3.1.1 Function Invocation

?A C++ program is made up of one or more

functions, one of which is main(). Program

execution always begins with main ().

?When program control encounters a

function name, the function is called, or

invoked.

?Demo on page 62: bell.cpp

3.2 Function Definition

?The C++ code that describes what a

function does is called the function

f u n c t i on

definition.

de f i n i t i on .

Its form is:

function header

f u n c t i on h e ade r

{

statements

s t at e m e n t s

}

3.2 Function Definition

?The function header is:

type name

t y pe n am e

( parameter-declaration-list)

par am e t e r - de c l ar at i on - l i s t )

?Sometimes the parameters in a function

definition are called formal parameters

f or m al par am e t e r s

to

emphasize their role as placeholders for

actual values that are passed to the function

when it is called.

?parameters in C++ are call-by-value.

c al l - by - v al u e .

?Demo on page 63: bellmult1.cpp

3.3 The return Statement

?The return

statement is used for two purposes.

?immediately passed back to the calling environment.

?the value of the expression is returned to the calling

environment

?A return

statement has one of the following two

forms:

?return;

?return

expression

e x p r e s i o n

;

?Demo on page 64: min_int.cpp

3.4 Function Prototypes

?A

function prototype is a function

declaration, but not a function definition.

?By explicitly declaring the return type and

the list of argument types, strong typechecking

and assignment-compatible

conversions for functions are possible in

C++.

3.4 Function Prototypes

?The function prototype

has the following

general form:

type

t y pe

name(argument

n am e ( ar gu m e n t

-declaration-list)

- de c l ar at i on - l i s t )

;

?The argument-declaration-list

ar gu m e n t - de c l ar at i on - l i s t

is either

empty, or a single declaration, or a comma

separated list of declarations. If a function

has no parameters, the keyword void may

be used.

3.4 Function Prototypes

?C++ uses the ellipsis symbol ( . . . ) to mean

an argument list that is unspecified. The

stdio.h function printf() is declared as the

prototype:

int printf(const char* cntrl_str, ...);

3.4 Function Prototypes

?Demo on page 66: add3.cpp

?function prototype

?expression converted to return type

?function definition

?optionally include arguments variable names

3.5 Default Arguments

?A formal parameter can be given a default

argument.

?Demon on page 68: def_args.cpp

3.6 Overloading Functions

?The usual reason for picking a function

name is to indicate the function's chief

purpose.

?Sometimes various functions are used for

the same purpose.

3.6 Overloading Functions

?Overloading

is using the same name for multiple

meanings of an operator or a function. The

meaning selected depends on the types of the

arguments used by the operator or function.

?Demo on page 69: avg_arr.cpp

?How overloaded function is invoked?

?The compiler chooses the function with matching types

and arguments.

?The signature matching algorithm

s i g n a t u r e m a t c h i n g a l g o r i t h m

gives the rules for

performing this.

3.7 Inlining

?C++ provides the keyword i n l i ne to

preface a function declaration when the

programmer intends the code replacing the

function call to be inline.

?Demo on page 70: inline_t.cpp

?Macro expansion

M ac r o e xpan s i on

is a scheme for placing

code inline that would normally use

function call.

?Demo on page 71: inline_t.cpp

3.7 Inlining

?One reason for all the parentheses is to

avoid precedence mistakes, as would occur

in the following:

#define SQR(x) x*x;

?

y=SQR(t+8);

3.8 Scope and Storage Class

?The kernel language has two principal

forms of scope: local scope

l oc al s c ope

and file scope.

f i l e s c ope .

?Local scope is scoped to a block.

?File scope has names that are external (global).

?Demo on page 72: scope_t.cpp

?In C++, the scope of an identifier begins at

the end of its declaration and continues to

the end of its innermost enclosing block.

3.8.1 The Storage Class auto

?Every variable and function in C++ kernel

language has two attributes: type

t y p e

and storage class.

s t o r a g e c l a s .

?The four storage classes are automatic, external,

register, and static, with the corresponding

keywords:

?auto

?extern

?register

?static

?A

compound statement with declarations is a

block.

b l o c k .

3.8.2 The Storage Class register

?The storage class register tells the compiler

that the associated variables should be

stored in high-speed memory registers,

provided it is physically and semantically

possible to do.

?The storage class register

is of limited

usefulness. It is taken only as advice

adv i c e

to the

compiler.

3.8.3 The Storage Class extern

?One method of transmitting information

across blocks and functions is to use

external variables.

?The keyword extern

is used to tell the

compiler to "look for it elsewhere, either in

this file or in some other file."

3.8.3 The Storage Class extern

?External variables never disappear.

?Information can be passed into a function

two ways: by external variables and by the

parameter mechanism.

?Demo on page 75: circle3.cpp

3.8.4 The Storage Class static

?Static declarations have two important and

distinct uses.

?The more elementary use is to allow a local

variable to retain its previous value when the

block is reentered.

?The second and more subtle use is in

connection with external declarations, and will

be discussed in the next section.

3.8.4 The Storage Class static

?Demo on page 76: stat_tst.cpp

?static variable is not reinitialized

?it provides a privacy

p r i v a c y

mechanism that is very

important for program modularity.

3.8.4 The Storage Class static

?Note that in C++

C +

systems that have

namespaces this mechanism can be replaced

by anonymous namespaces.

?In C++,

C + ,

both external variables and static

variables that are not explicitly initialized

by the programmer are initialized to zero by

the system.

?In contrast, automatic and register variables

usually are not initialized by the system.

3.8.5 Linkage Mysteries

?Multi-file programs require proper linkage.

3.8.5 Linkage Mysteries

?Linkage to C code is possible using the

form:

extern "C"

{ code or included file

c ode or i n c l u de d f i l e

}

?Linkage to other languages beside C is

system-dependent.

3.9 Namespaces

?C++ encourages multi-vendor library use.

This motivates the addition to ANSI C++ of

a namespace

n am e s pac e

scope:

namespace

LMPinc

{

class puzzles {

?

} ;

class toys

{ . . . } ;

. . . . .

}

3.9 Namespaces

?The namespace identifier

n am e s pac e i de n t i f i e r

can be used as

part of a scope resolved identifier. This has

the form:

?namespace_id

n am e s pac e _d

:

:

: id

i d

?There is also a using

declaration that lets a

client have access to all names from that

namespace. For example:

using namespace

LMPi

nc

;

toys top; //

LMPi

nc

: : toys

3.9 Namespaces

?Demo on page 78: namespac.cpp

?namespaces can be used to provide a unique

scope replacing the use of static global

declarations. This is done by an anonymous

namespace definition, as in:

namespace

{ int

count

= 0;

} //count i s unique here

//count i s available i n the rest of the f i l e

void chg_cnt(int

i)

{ count

= i

; }

?The new ANSI conforming library headers

will no longer use the .h

suffix.

3.10 Pointer Types

?C++ pointers

C + poi n t e r s

are used to reference variables

and machine addresses.

?Pointers are used in programs to access

memory and manipulate addresses.

p

= &i;

// the address of object i

p

= 0;

// a special sentinel value

p

= static_cast

<

int

>(1507)

; // an absolute address

3.10.1 Addressing and

Dereferencing

?The dereferencing

or indirection

operator *

is

unary, and has the same precedence and right-toleft

associativity as the other unary operators.

int

i

= 5 , j;

int

*

p

= & i ; //pointer i n i t to address of i

cout

<< *

p

<< 'I

= i stored a t

" << p

<< endl

;

j

= p; / / illegal pointer not convertible to integer

j

= *

p

+ 1; //legal

p

= &j; //p points to j

3.10.2 Pointer-Based Call-by-

Reference

?In this section, we describe how the

addresses of variables can be used as

arguments to functions so the stored values

of the variables can be modified in the

calling environment, thus simulating callby-

reference.

?Demo on page 80: call_ref.cpp

?These pointers are passed call-by-value

?parameter is pointer

?access variables out of function

3.10.2 Pointer-Based Call-by-

Reference

?Call-by-Reference Using Pointers

?1. Declare a pointer parameter in the function

header.

?2. Use the dereferenced pointer in the function

body.

?3.

Pass an address as an argument when the

function is called

3.11 The Uses of void

?The keyword void is used as the return type

of a function not returning a value.

?A

more important use is to declare the

generic pointer

ge n e r i c poi n t e r

type-pointer to void.

3.11 The Uses of void

?A further use of void

given as the parameter

list in a function declaration means the

function takes no arguments.

?int

foo

();

?int

foo(void

);

3.11 The Uses of void

?Any pointer type can be converted to a

generic pointer of type void

*

.

?Other pointer conversions include:

?the name of an array is a pointer to its base

element;

?the null pointer value can be converted to any

type;

?the type "function returning T"

can be

converted to pointer to function returning T.

3.12 Arrays and Pointers

?An array is a data type that is used to

represent a sequence of homogeneous

values.

?Demo on page 82: sum_arr1.cpp

3.12.1 Subscripting

?Assume that a declaration of the form

int i, a[size];

?we may write a [expr] , where expr is an

integral expression, to access an element of the

array. We call expr a subscript, or index, of a.

?The value of a C++ subscript should lie in the

range 0 to size - 1.

?An array subscript value outside this range

often causes a run-time error.

3.12 .2 Initialization

?Arrays can be initialized by a commaseparated

list of expressions enclosed in

braces.

?An array declared with an explicit initializer

list and no size expression is given the size

of the number of initializers.

3.1 3 The Relationship between

Arrays and Pointers

?An array name by itself is an address, or

pointer value,

v al u e ,

and pointers and arrays are

almost identical in terms of how they are

used to access memory.

?A pointer is a variable that takes addresses

as values. An

array name is a particular

fixed address that can be thought of as a

constant pointer.

3.1 3 The Relationship between

Arrays and Pointers

?Example code

const int N=100;

int a[N],*p;

p=a;

p=&a[0];

p=a+1;

p=&a[1];

?Demo on page 85: sum_arr2.cpp

3.1 3 The Relationship between

Arrays and Pointers

?In many ways, arrays and pointers can be

treated alike, but there is one essential

difference.

?Arrays are constants.

?Note that sizeof

s i z e o f

(a)

( a )

and sizeof

s i z e o f

(p)

( p )

are different.

?The first expression is the size of the entire array,

?while the second is the size of a pointer expression.

3.14 Passing Arrays to Functions

?As a notational convenience, the compiler

allows array bracket notation

br ac ke t n ot at i on

to be used in

declaring pointers as parameters.

?Demo on page 86: sum_arr3.cpp

3.15 Reference Declarations and

Call-by-Reference

?Reference declarations declare the identifier to be

an alternative name, or alias, for an object

specified in an initialization of the reference, and

allow a simpler form of call-by-reference

parameters.

int

n;

int

&

nn

= n //

nn

i s alternative name for n

double a[10]

;

double& last

= a[9]; / / last is an alias for a[9]

3.15 Reference Declarations and

Call-by-Reference

?Declarations of references that are

definitions must be initialized, and are

usually initialized to simple variables.

?The initializer is an lvalue expression,

which gives the variable's location in

memory.

3.15 Reference Declarations and

Call-by-Reference

?The following definitions are used to

demonstrate the relationship of pointers,

dereferencing, and aliasing.

3.15 Reference Declarations and

Call-by-Reference

?Demo on page 88: sim_call.cpp

?Demo on page 89: greater.cpp

3.16 Assertions and Program

Correctness

?Assertions are program checks for correctness that,

if violated, force an error exit.

?add precondition

?add postcondition

?Demo on page 90: order.cpp

?The precondition assertion in place_min () guarantees

that a nonnegative number of elements will be searched.

?The postcondition in main () checks that the minimum

element was found and placed in the correct position.

3.1 7 Strings: The char* Convention

?The C and C++ communities have "agreed"

to treat the type char

c h ar

*

*

as a form of string

s t r i n g

type.

?The understanding is that these strings will

be terminated by the char value zero, and

that the cstring

c s t r i n g

(

(

string.h

s t r i n g. h

on older systems)

package of functions will be called on this

abstraction.

3.1 7 Strings: The char* Convention

?Some Functions in the

cstring

c s t r i n g

Library

iraybLr

?size_t

strlen(const

tsceronn

char

*

s) ;

?Computes the string length.

?char

*

strcpy(charc

tscrayhp(s1, const char

rn

*

s2);

?Copies the string s2 into sl. The value of sl is

returned.

?int

strcmp(const

tscropmn

char

*

s l , const char

ltscaohrn

*

s2);

?Returns an integer that reflects the lexicographic

comparison of s l and s2. When the strings are

the same zero is returned. When s l is less than

s2, a negative integer is returned. When s2 is less

than s l , a positive integer is returned.

3.1 7 Strings: The char* Convention

?Demo on page 92-93: str_func.cpp

3.18 Multidimensional Arrays

?C++ allows arrays of any type, including

arrays of arrays.

?A

k-dimensional array has a size for each of

its k dimensions.

3.19 Free Store Operators new and

delete

?The unary operators new

and delete

are

available to manipulate free store.

?Free store is a

system-provided memory

pool for objects whose lifetime is directly

managed by the programmer.

?The programmer creates the object by using

new

and destroys it by using delete.

3.19 Free Store Operators new and

delete

?In C++, operator new

is used in the

following forms:

new type-name

teaynwpm

new type-name

initializer

iterzanl

new type -

name[expression

seraoxnnpm

]

3.19 Free Store Operators new and

delete

?The operator delete has the following forms:

delete

expression

e xpr e s i on

delete []

expression

e xpr e s i on

?Demo on page 95: dynarray.cpp

?dynamically allocated array

?use delete to free store.

3.20 Pragmatics

?When function arguments are to remain

unmodified, it can be efficient and correct

to pass them const call-by-reference.

3.20 Pragmatics

?For variables that are not to be changed and

whose memory requirements are small, callby-

value is usual.

?ANSI C allows the narrowing conversion

from void* to an arbitrary pointer type, but

C++ does not.

3.20 Pragmatics

?The widening conversion from specific to

generic pointer type is safe and allowed

implicitly.

?The narrowing conversion from generic to

specific pointer type is potentially unsafe

and system-dependent.

?reinterpret_caste<>

3.20.2 Replacing s t a t i c extern

Declarations

?Anonymous namespaces (see Section 3.9,

"Namespaces," on page 78) should be used

to provide a unique scope replacing the use

of static global declarations.

namespace{int seed = 0; } //makes a unique name

void srand(int i){ seed = i ;} //unique::seed

Summary

?1. function deceleration and definition

?2. In C++, a function cannot be used until it is

declared.

?3. A

return statement is used to exit a function.

?4. An array is a data type that is used to represent

a sequence of homogeneous values.

?5. The four storage classes are automatic, external,

register, and static.

Summary

?6. C++ pointers are used to reference variables and

machine addresses.

?7. Reference declarations allow an object to be

given an alias or alternate name.

?8. The declaration void

*

is a generic pointer type.

?9. In a function definition, a formal parameter that

is declared as an array is actually a pointer.

?10. The unary operators new

and delete

are

available to manipulate free store. 

继续阅读