• No se han encontrado resultados

ANÁLISIS DEL MINILIBRO INFANTIL: MARIPOSA AZUL

ANÁLISIS DE LAS OBRAS REPRESENTATIVAS DE SOLEDAD CÓRDOVA

3.3. ANÁLISIS DEL MINILIBRO INFANTIL: MARIPOSA AZUL

In C, a function itself is not a variable, but it is possible to define pointers to functions, which can be assigned, placed in arrays, passed to functions, returned by functions, and so on [KR88, page 118].

Function pointers are a very useful mechanism for selecting, substituting or grouping together functions of a particular form. For example, they may be used to pass functions as arguments to other functions. Or, they may be collected into an array of function pointers as a “dispatch table”, where a certain function is invoked based on an array index.

The declaration of a function pointer must specify the number and type of the function arguments and the function return type. For example, the following declaration is a pointer to a function that has adoubleand anintargument and returns adouble.

double (*pf)(double, int);

Thus, it is not possible to define a completely generic function pointer, only one that points to a certain category of function that fits the declaration.

Notice the use of parentheses around the identifier (*pf). This is necessary to distinguish a pointer-to-a-function from a function-that-returns-a-pointer.

int (*pf)(char); /* pointer-to-function: input char, return int */

int *f(char); /* function: input char, return pointer-to-int */

In a function declaration, it is possible to declare a function pointer without using an identifier; (this is the case also with any other function argument).

void myfunc(char *, int, unsigned (*)(int));

However, it is usually better practice to include identifiers in function prototypes, as it improves readability.

void myfunc(char *message, int nloops, unsigned (*convert)(int));

The following example program uses function pointers to pass functions as arguments to another function. This allows the the latter function to perform a variety of operations without any change to its own algorithm. (Notice that, like arrays, function names are automatically converted to pointers without using the address-of operator&.)

1 #include<stdio.h>

2 #include<assert.h>

3

4 doubleadd(doublea,doubleb){returna +b;} 5 doublesub(doublea,doubleb){returnab;} 6 doublemult(doublea,doubleb){ returna *b;}

7 doublediv(doublea,doubleb){assert(b!= 0.0);returna/ b;} 8

9 voidexecute operation(double(*f)(double,double), doublex,doubley) 10 {

11 doubleresult=f(x,y);

12 printf("Result of operation on %3.2f and %3.2f is %7.4f\n",x,y,result);

13 } 14

15 intmain(void) 16 {

17 doubleval1=4.3,val2=5.7;

18 execute operation(add,val1,val2);

19 execute operation(sub,val1,val2);

20 execute operation(mult,val1,val2);

21 execute operation(div,val1,val2);

22 }

Function pointers may be used to separate out certain sub-algorithm operations from within a general purpose main algorithm. This allows different sub-algorithms to be swapped in or out at run time. A common example is a generic sorting algorithm that uses function pointers to implement its sorting criterion.

void generic_sort(int *array, int len, int (*compare)(int, int));

int greater_than(int a, int b) { return a > b; } /* Possible sorting criterion. */

int less_than(int a, int b) { return a < b; } /* Possible sorting criterion. */

generic_sort(values, 20, less_than); /* Using the sort algorithm. */

Chapter 8

Arrays and Strings

An array is a group of variables of a particular type occupying a contiguous region of memory. In C, array elements are numbered from 0, so that an array of sizeN is indexed from 0 toN−1. An array must contain at least one element, and it is an error to define an empty array.

double empty[0]; /* Invalid. Won’t compile. */

8.1 Array Initialisation

As for any other type of variable, arrays may have local, external or static scope. Arrays with static extent have their elements initialised to zero by default, but arrays with local extent are not initialised by default, so their elements have arbitrary values.

It is possible to initialise an array explicitly when it is defined by using an initialiser list. This is a list of values of the appropriate type enclosed in braces and separated by commas. For example,

int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

If the number of values in the initialiser list is less than the size of the array, the remaining elements of the array are initialised to zero. Thus, to initialise the elements of an array withlocal extent to zero, it is sufficient to write

int localarray[SIZE] = {0};

It is an error to havemore initialisers than the size of the array.

If the size of an array with an initialiser list is not specified, the array will automatically be allocated memory to match the number of elements in the list. For example,

int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

the size of this array will be twelve. The size of an array may be computed via thesizeofoperator, int size = sizeof(days); /* size equals 12 * sizeof(int) */

which returns the number ofcharacters of memory allocated for the array. A common C idiom is to usesizeofto determine the number of elements in an array as in the following example.

nelems = sizeof(days) / sizeof(days[0]);

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

printf("Month %d has %d days.\n", i+1, days[i]);

This idiom is invariant to changes in the array size, and computes the correct number of elements even if the type of the array changes.1 For this reason, an expression of the form

sizeof(array) / sizeof(array[0]) is preferred over, for example,

sizeof(array) / sizeof(int)

asarraymight one day become an array of type unsigned long.

Note. sizeofwill only return the size of an array if it refers to the original array name. An array name is automatically converted to a pointer in an expression, so that any other reference to the array will not be an array name but a pointer. For example,

int *pdays = days;

int size1 = sizeof(days); /* size1 equals 12 * sizeof(int) */

int size2 = sizeof(days + 1); /* size2 equals sizeof(int *) */

int size3 = sizeof(pdays); /* size3 equals sizeof(int *) */

Similarly, if an array is passed to a function, it is converted to a pointer.

int count_days(int days[], int len) {

int total=0;

/* assert will fail: sizeof(days) equals sizeof(int *) and len equals 12 */

assert(sizeof(days) / sizeof(days[0]) == len);

while(len--)

total += days[len];

return total;

}