2009-08-25 15 views
57

Dado el siguiente programa,Cuando una función tiene un parámetro de matriz de tamaño específico, ¿por qué se reemplaza con un puntero?

#include <iostream> 

using namespace std; 

void foo(char a[100]) 
{ 
    cout << "foo() " << sizeof(a) << endl; 
} 

int main() 
{ 
    char bar[100] = { 0 }; 
    cout << "main() " << sizeof(bar) << endl; 
    foo(bar); 
    return 0; 
} 

salidas

main() 100 
foo() 4 
  1. ¿Por qué es la matriz pasada como un puntero al primer elemento?
  2. ¿Es un patrimonio de C?
  3. ¿Qué dice la norma?
  4. ¿Por qué se descarta la estricta seguridad de tipo de C++?
+0

siempre uso std :: matriz en estos casos, evita tener que lidiar con temas como este y funciona con algoritmos std demasiado estricta – paulm

+2

Qué tipo de seguridad? ¿Quién ha prometido seguridad de tipo estricto? No existe tal cosa en C++. –

+0

TL; DR para las siguientes respuestas: Las matrices se convierten en punteros cuando se pasan a la función, por lo que cuando se comprueba su tamaño, todo lo que se obtiene es el tamaño de un puntero. Si trabajas solo con C, todo lo que puedo sugerirte es que calcules cualquier otro parámetro que intentes sacar de la matriz. –

Respuesta

63

Sí, es heredado de C. La función:

void foo (char a[100]); 

tendrá el parámetro ajustado para ser un puntero, y por lo tanto se convierte en:

void foo (char * a); 

Si desea conservar el tipo de matriz, debe pasar una referencia a la matriz:

void foo (char (&a)[100]); 

C++ '03 8.3.5/3:

... El tipo de una función se determina usando las siguientes reglas. El tipo de cada parámetro se determina a partir de su propio decl-specifier-seq y declarator. Después de determinar el tipo de cada parámetro, cualquier parámetro de tipo "matriz de T" o "función que devuelve T" se ajusta para que sea "puntero a T" o "puntero a función que devuelve T", respectivamente ....

para explicar la sintaxis:

de verificación "derecha-izquierda" regla de Google; Encontré una descripción de él here.

Se aplicaría a este ejemplo aproximadamente como sigue:

void foo (char (&a)[100]); 

inicio al identificador 'a'

'a' es un derecho

Mover - nos encontramos a ), así que invertimos la dirección buscando (. A medida que avanzamos izquierda pasamos &

'a' es una referencia

Después de la & llegamos a la apertura ( así que invertimos de nuevo y se ve bien. Ahora vemos [100]

'a' es una referencia a un array de 100

Y que invierten el sentido de nuevo hasta llegar a char:

'a' es una referencia a una matriz de 100 caracteres

+1

Este último tiene la desventaja de cablear el tamaño de la matriz en la firma de la función. Una plantilla de función puede evitar eso. – sbi

+0

En una nota algo relacionada, ¿podría alguien aclarar la sintaxis de lo anterior para mí? Obviamente me falta algo, pero no veo cómo se evalúa una referencia a una matriz; parece más una variedad de referencias. – suszterpatt

+4

es probable que valga la pena mencionar que el uso de std :: vector alineará todos los problemas relacionados con el paso de matrices. – markh44

12

Sí. En C y C++ no puede pasar matrices a las funciones. Esa es la forma como es.

¿Por qué estás haciendo matrices simples de todos modos? ¿Ha mirado boost/std::tr1::array/std::array o std::vector?

Tenga en cuenta que puede, sin embargo, pasar una referencia a una matriz de longitud arbitraria a una plantilla de plantilla. De la parte superior de mi cabeza:

template< std::size_t N > 
void f(char (&arr)[N]) 
{ 
    std::cout << sizeof(arr) << '\n'; 
} 
+5

Pero puede pasar "referencia a matriz". –

+0

Solo un código heredado – CsTamas

+0

@Richard: Solo añadí esto mientras escribía su comentario. ':)' – sbi

1

Hay una palabra magnífica en la terminología C/C++ que se utiliza para matrices estáticas y punteros d función - decaimiento. Considere el siguiente código:

int intArray[] = {1, 3, 5, 7, 11}; // static array of 5 ints 
//... 
void f(int a[]) { 
    // ... 
} 
// ... 
f(intArray); // only pointer to the first array element is passed 
int length = sizeof intArray/sizeof(int); // calculate intArray elements quantity (equals 5) 
int ptrToIntSize = sizeof(*intArray); // calculate int * size on your system 
+1

Y? Esto, en el mejor de los casos, indica indirectamente lo que sucede. El OP preguntaba por qué el lenguaje está configurado de esa manera. Además, "matriz estática" es un término confuso cuando lo que realmente quiere decir se asigna dinámicamente; técnicamente, la matriz que has mostrado tiene una vinculación 'extern', no' estática'. ¿Y no estoy seguro de qué función tienen los punteros para hacer algo aquí? –

Cuestiones relacionadas