2011-03-30 19 views
17

Duplicar posibles:
How to find the sizeof(a pointer pointing to an array)C sizeof una matriz pasada

entiendo que el operador sizeof se evalúa y se reemplaza con una constante en tiempo de compilación. Dado que, ¿cómo puede una función, al pasar diferentes matrices en diferentes puntos de un programa, tener su tamaño calculado? Puedo pasarlo como un parámetro a la función, pero prefiero no tener que agregar otro parámetro si no es absolutamente necesario.

He aquí un ejemplo para ilustrar lo que estoy preguntando:

#include <stdio.h> 
#include <stdlib.h> 

#define SIZEOF(a) (sizeof a/sizeof a[0]) 


void printarray(double x[], int); 

int main() 
{ 
     double array1[ 100 ]; 


     printf("The size of array1 = %ld.\n", SIZEOF(array1)); 
     printf("The size of array1 = %ld.\n", sizeof array1); 
     printf("The size of array1[0] = %ld.\n\n", sizeof array1[0]); 

     printarray(array1, SIZEOF(array1)); 

     return EXIT_SUCCESS; 
} 


void printarray(double p[], int s) 
{ 
     int i; 


     // THIS IS WHAT DOESN"T WORK, SO AS A CONSEQUENCE, I PASS THE 
     // SIZE IN AS A SECOND PARAMETER, WHICH I'D RATHER NOT DO. 
     printf("The size of p calculated = %ld.\n", SIZEOF(p)); 
     printf("The size of p = %ld.\n", sizeof p); 
     printf("The size of p[0] = %ld.\n", sizeof p[0]); 

     for(i = 0; i < s; i++) 
       printf("Eelement %d = %lf.\n", i, p[i]); 

     return; 
} 
+0

Estándar C gotcha - vea el enlace a la pregunta. – Jon

+0

'sizeof' no tiene que evaluarse en tiempo de compilación en C99 - Los VLA funcionan correctamente con' sizeof', y su tamaño solo puede conocerse en tiempo de ejecución. –

Respuesta

11

No hay una solución mágica. C no es un lenguaje reflexivo. Los objetos no saben automáticamente lo que son.

Pero usted tiene muchas opciones:

  1. Obviamente, agregue un parámetro
  2. Wrap la llamada en una macro y añadir automáticamente un parámetro
  3. Utilice un objeto más complejo. Define una estructura que contiene la matriz dinámica y también el tamaño de la matriz. Luego, pase la dirección de la estructura.
1

Puede utilizar un valor centinela, que es la forma como las cadenas se tratan. El inconveniente es que debe iterar sobre toda la matriz para encontrar su tamaño.

Por ejemplo, cuando se tiene una cadena como:

char s1[] = "foobar"; 

Lo que realmente tiene es una matriz de longitud 7, con el séptimo lugar de ser un nulo carbón terminador '\ 0' que sirve para indicar el final de la matriz/cadena.

Otra forma de hacerlo es crear una estructura que consta de un tamaño seguido de la matriz.

0

Debe ya sea

  1. Pase el tamaño de la matriz como un parámetro a la función
  2. Asegúrese de que la matriz termina con un valor conocido, y se detendrá cuando llegue a ese valor.
0

Si su matriz tiene un final nulo, puede recorrer la matriz y encontrar el último valor. Muchos operadores de cadenas en C funcionan de esa manera

De lo contrario, no tiene muchas opciones.

sizeof devuelve el tamaño de p, que es un puntero y la voluntad es igual al tamaño de su int

6

parámetros de función en realidad nunca tienen el tipo de matriz.Cuando el compilador ve

void printarray(double p[], int s) 

o incluso

void printarray(double p[100], int s) 

que convierte a cualquiera

void printarray(double* p, int s) 

Así sizeof(p) es sizeof(double*). Y sí, tendrás que pasar el tamaño como un parámetro.

1

Respondió su propia pregunta. Se calcula en tiempo de compilación, entonces, ¿cómo puede 'sizeof p' posiblemente tener más de un valor durante el tiempo de ejecución?

Pasar la longitud como un parámetro es una buena solución, de lo contrario puede asegurarse de que sus matrices siempre terminen con algún valor especial (como cadenas y el byte nulo).

5

El problema es que su función no recibe un valor de matriz; recibe un valor de puntero.

excepto cuando es el operando de los sizeof o unario & operadores, o es una cadena literal que se utiliza para inicializar otra matriz en una declaración, una expresión de tipo "array de T" se convertirá en el tipo "puntero a T "y su valor será la dirección del primer elemento de la matriz.

Por lo tanto, cuando se llama printarray, el tipo de array1 se convierte implícitamente a partir de "matriz de 100 elementos de double" a "puntero a double." Por lo tanto, el tipo del parámetro p es double *, no double [100].

En el contexto de una declaración de parámetro de función, T a[] es idéntico a T *a.

Es por eso que debe pasar el tamaño de la matriz por separado;