tutorial smart remix español curso aprender c++ c arrays function pointers

c++ - smart - solidity ide



Puntero a una matriz de tamaño no especificado "(* p)[]" ilegal en C++ pero legal en C (2)

C ++ no tiene la noción de C del "tipo compatible". En C, esta es una redeclaración perfectamente válida de una variable:

extern int (*a)[]; extern int (*a)[3];

En C, esta es una redeclaración perfectamente válida de la misma función:

extern void f(); extern void f(int);

En C, esto es específico de la implementación, pero generalmente es una redeclaración válida de la misma variable:

enum E { A, B, C }; extern enum E a; extern unsigned int a;

C ++ no tiene nada de eso. En C ++, los tipos son los mismos, o son diferentes, y si son diferentes, entonces hay muy poca preocupación en lo diferentes que son.

Similar,

int main() { const char array[] = "Hello"; const char (*pointer)[] = &array; }

es válido en C, pero no válido en C ++: la array , a pesar de [] , se declara como una matriz de longitud 6. El pointer se declara como un puntero a una matriz de longitud no especificada, que es un tipo diferente. No hay conversión implícita de const char (*)[6] a const char (*)[] .

Debido a eso, las funciones que toman punteros a arreglos de longitud no especificada son bastante inútiles en C ++, y casi con certeza un error por parte del programador. Si comienzas desde una instancia de matriz concreta, casi siempre tienes el tamaño, por lo que no puedes tomar su dirección para pasarla a tu función, porque tendrías una discrepancia de tipo.

Y tampoco hay necesidad de punteros a matrices de longitud no especificada en su ejemplo: la forma normal de escribir eso en C, que también es válida en C ++, es

int accumulate(int n, int *array) { int i; int sum = 0; for (i = 0; i < n; ++i) { sum += array[i]; } return sum; }

ser llamado como accumulate(ARRAY_LENGTH(a), a) .

Acabo de descubrir que esto es ilegal en C ++ (pero legal en C):

#include <stdio.h> #include <stdlib.h> #define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0])) int accumulate(int n, const int (*array)[]) { int i; int sum = 0; for (i = 0; i < n; ++i) { sum += (*array)[i]; } return sum; } int main(void) { int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35}; printf("%d/n", accumulate(ARRAY_LENGTH(a), &a)); return 0; }

Compila sin problemas usando gcc -std=c89 -pedantic pero no puede compilar usando g++ . Cuando intento compilarlo usando g++ obtengo estos mensajes de error:

main.cpp:5:37: error: parameter ''array'' includes pointer to array of unknown bound ''int []'' int accumulate(int n, int (*array)[]) ^ main.cpp: In function ''int main()'': main.cpp:18:50: error: cannot convert ''int (*)[9]'' to ''int (*)[]'' for argument ''2'' to ''int accumulate(int, int (*)[])'' printf("%d/n", accumulate(ARRAY_LENGTH(a), &a));

He estado usando esto en mi código C durante mucho tiempo y no tenía idea de que fuera ilegal en C ++. Para mí, esto parece una forma útil de documentar que una función toma una matriz cuyo tamaño no se conoce de antemano.

Quiero saber por qué esto es legal C pero no válido C ++. También me pregunto qué fue lo que hizo que el comité de C ++ decidiera quitárselo (y rompiendo esta compatibilidad con C).

Entonces, ¿por qué este código C legal es un código C ++ ilegal?


Dan Saks escribió sobre esto en 1995 , durante el proceso previo a la estandarización de C ++:

Los comités decidieron que funciones como esta, que aceptan un puntero o referencia a una matriz con límite desconocido, complican la coincidencia de declaraciones y las reglas de resolución de sobrecarga en C ++. Los comités acordaron que, dado que tales funciones tienen poca utilidad y son bastante poco comunes, sería más simple simplemente prohibirlas. Por lo tanto, el borrador de C ++ ahora declara:

Si el tipo de un parámetro incluye un tipo de puntero de formulario a una matriz de límite desconocido de T o una referencia a una matriz de límite desconocido de T, el programa está mal formado.