Disponible la nueva versión "donationware" 7.3 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 ...