Disponible la versión 6 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


Apéndice 6.1  Reglas de lectura


Nota
:  Este apéndice no debe ser considerado tema de estudio en una primera lectura.  La notación y sintaxis de las entidades C++ son contempladas en los epígrafes correspondientes.  Aquí se incluye simplemente una recopilación de casos relativos a matrices, funciones y punteros (los más propensos a una notación complicada), que puede utilizarse una vez que se ha realizado una primera aproximación al lenguaje.


§1  Sinopsis

Lanotación de C/C++ tiende a ser algo confusa, sobre todo para el principiante.  Algunas veces las expresiones son realmente difíciles de interpretar.  Por ejemplo:

void (_USERENTRY *signal(int sig, void (_USERENTRY *func) (int sig[, int subcode])))(int);

verdaderamente es una expresión para nota; representa el prototipo de la función signal, definida en <signal.h> de la Librería Estándar, la analizaremos más adelante; por ahora, seguiremos con alguna más sencilla, por ejemplo:

int (* afpt[10])(char);

declara que afpt es una matriz de diez punteros a función que reciben un char y devuelven int.  Por su parte:

int* aptr[10];

declara aptr como matriz de diez punteros a entero, mientras que:

int (*ptai)[10]

declara ptai como puntero a matriz de diez enteros.  Finalmente:

int (*(*(*fptr)(char))[5])();

declara que fpta es un puntero a función que recibe un char y devuelve un puntero a matriz de 5 punteros a función que no reciben ningún parámetro y devuelven int.


Como regla general, en este tipo de expresiones es necesario buscar el identificador, a partir de este punto, moverse sucesivamente a derecha e izquierda, deteniéndose en los posibles paréntesis, y teniendo en cuenta que:

()       significa función, eventualmente incluyendo tipo de parámetros.  "función recibiendo ..."

*         significa puntero  "puntero a:"

[ ]       significa matriz, eventualmente incluyendo la dimensión:  "matriz de ..."


§2  Ejemplos

Para ilustrarlo con unos ejemplos efectuemos el análisis de algunas expresiones mostrando paso a paso el proceso seguido:

Expresión:          (* name[])()

identificador:     →   name

name[]            →  name: matriz

* name[]        →  name: matriz de punteros

(* name[])()  → name: matriz de punteros a función

Expresión:           int (* name)[10]

identificador:           →  name

* name                   →  name: puntero a

(* name)[10]       →  name: puntero a matriz de 10

int (*name)[10] →  name: puntero a matriz de 10 enteros

Expresión:           int * name[10]

identificador:           →  name

name[10]             →  name: matriz de 10

* name10]           →  name: matriz de 10 punteros

int * name[10] →  name: matriz de 10 punteros a entero

Expresión:           int name(char)

identificador:          →  name

name(char)        →  name: función recibiendo char

int name(char)  →  name: función recibiendo char y devolviendo entero

Expresión:           int *name(char)

identificador:             →  name

name(char)           →  name: función recibiendo char

* name(char)      →  name: función recibiendo char devolviendo puntero a

int *name(char) →  name: función recibiendo char devolviendo puntero a int

Expresión:           int (* name)(char)

identificador:                →  name

* name                      →  name: puntero a

(* name)(char)      →  name: puntero a función recibiendo char

int (*name)(char)  →  name: puntero a función recibiendo char devolviendo int

Expresión:            int (*(*name())[2])()

identificador:              →  name

name()                    →  name: función (no recibe argumentos)

(*name())              →  name: función devolviendo puntero a

(*name())[2]        →  name: función devolviendo puntero a matriz de dos...

(*(*name())[2])              →  name: función devolviendo puntero a matriz de dos punteros a...

(*(*name())[2])()          →  name: función devolviendo puntero a matriz de dos punteros a función...

int (*(*name())[2])()  →  name: función devolviendo puntero a matriz de dos punteros a función que devuelven int

Expresión:           int (*(*name())[])(char)

identificador:              →  name

name()                    →  name: función (no recibe argumentos)

(*name())              →  name: función devolviendo puntero a

(*name())[]          →  name: función devolviendo puntero a matriz (no se indica dimensión)

*(*name())[]        →  name: función devolviendo puntero a matriz de punteros a

(*(*name())[])(char) →  name: función devolviendo puntero a matriz de punteros a función recibiendo char

int (*(*name())[])(char) →  name: función devolviendo puntero a matriz de punteros a función recibiendo char devolviendo int.

Expresión:           int (*(*name[2])())[3]

identificador:             →  name

name[2]                 →  name: matriz de dos

(*name[2])           →  name: matriz de dos punteros a

(*name[2])()       →  name: matriz de dos punteros a función  (no recibe argumentos)

*(*name[2])()     →  name: matriz de dos punteros a función devolviendo puntero a

(*(*name[2])())[3] →  name: matriz de dos punteros a función devolviendo puntero a matriz de tres

int (*(*name[2])())[3] →  name: matriz de dos punteros a función devolviendo puntero a matriz de tres enteros.

Expresión:        void* (*(*name)(int))[5]

identificador:             →  name

*name                     →  name: puntero

(*name)(int)       →  name: puntero a función que recibe un entero

*(*name)(int)     →  name: puntero a función que recibe un entero y devuelve un puntero...

(*(*name))[5]            →  name: puntero a función que recibe un entero y devuelve un puntero a matriz de 5 elementos...

void* (*(*name))[5] →  name: puntero a función que recibe un entero y devuelve un puntero a matriz de 5 punteros a void

Expresión:      void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const void *));

Se trata de un caso real, el prototipo de la función qsort de la Librería Standar. Para simplificar dejamos la expresión en su estructura, olvidándonos de los detalles de nombres:

void qsort(void *, size_t, size_t, int (*fcmp)(const void *, const void *));

identificador:             →  qsort

qsort(,,,             →  qsort: función recibiendo cuatro parámetros...

void qsort(,,,) →  qsort: función recibiendo cuatro parámetros y no devolviendo nada.

podemos ahora concentrarnos en los parámetros:

void *    →  primer argumento:  puntero de tipo genérico.

size_t    →  segundo y tercero:  variables de tipo size_t. Es el tipo estándar C para los tamaños, por ejemplo es el tipo que hay que pasar a malloc(), en nuestro caso está definido como unsigned (int).

int (*fcmp)(const void *, const void *)  →  cuarto parámetro:  procedemos a analizarlo separadamente:

identificador                    →  fcmp (del parámetro)

*fcm                             →  fcmp: puntero

(*fcmp)(..,..)         →  fcmp: puntero a función recibiendo dos argumentos tipo puntero genérico a constante.

int (*fcmp)(..,..) →  fcmp: puntero a función recibiendo... y devolviendo un entero.

Expresión:            void (_USERENTRY *name)(int)

identificador:           →  name

*name                   →  name: puntero a

*name)(int)       →  name: puntero a función recibiendo un int

(_USERENTRY *name)(int) →  name: puntero a función recibiendo un int, debe usarse la convención de llamada _USERENTRY

void (_USERENTRY *name)(int)  →  name: puntero a función recibiendo un int según la convención de llamada _USERENTRY y que  no devuelve nada.

Expresión:         void (_USERENTRY *signal(int sig, void (_USERENTRY *func) (int sig[, int subcode])))(int);

Para simplificar dejaremos la expresión en su estructura e iremos añadiendo detalles:

void (*signal(int, void (*func)(int)))(int);

identificador:         →  signal

signal(...)     →  signal: función

signal(int, void (*func)(int))) →  signal: función recibiendo dos parámetros, un int y ...