2011-08-27 8 views
11

Leí en un libro C que para una matriz num[7] el término num es equivalente a &num[0]. Este concepto funcionaba bien para mí, pero cuando escribí este programa que se muestra a continuación, nuevamente me confundí.Dado `int num [7]`, ¿cómo se diferencian `num`,` & num [0] `,` & num`?

#include<stdio.h> 
#include<conio.h> 
int main() 
{ 
    int num[]={21,22,23,24,25,26,27}; 
    int *x,*y,*z; 
    x=&num; 
    y=num; 
    z=&num[0]; 
    printf("%d %d %d\n",sizeof(x),sizeof(y),sizeof(z)); 
    printf("%d %d %d\n",sizeof(&num),sizeof(num),sizeof(&num[0])); 
    printf("%d %d %d",*(&num),*(num),*(&num[0])); 
    getch(); 
    return 0; 
} 

salida es:

 4 4 4 
     4 28 4 
     2293536 21 21 

Si num es idéntica a &num[0] entonces ¿por qué hay una diferencia en su tamaño? ¿Y cuál es este tercer tipo de término &num? Sé que está mostrando un valor de basura, pero ¿tiene sentido este tipo de término? z=&num[0] Ya lo entiendo. El compilador muestra una advertencia para la asignación x=&num, pero para el y=num; el compilador no tiene ningún problema. Si num tiene el tamaño 28, ¿por qué se asignó a un puntero entero y sin un tipocast?

Luego probé en la matriz 2-D de esta manera:

#include<stdio.h> 
#include<conio.h> 
int main() 
{ 
    int s[4][2]={{1234,56},{1235,57},{1236,58},{1237,59}}; 
    int i 
    printf ("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s), 
     sizeof(s[0][0]),sizeof(&s)); 
    getch(); 
    return 0; 
} 

Ahora el resultado es

8 4 32 4 4 

Aquí sizeof(s[i]) es 8. porque s[i] es una matriz 1-D y tiene dos elementos, por lo que está bien. Pero no tengo idea de qué significan los términos &s[i] y &s. Y nuevamente puedo ver que s no es idéntico a s[0][0]. He utilizado la versión Dev C++ 4.9.9.2 para ejecutar todos los programas. Quiero ser claro en estos tres tipos de términos.

+2

Lea las preguntas frecuentes C que tiene una sección entera dedicada a este tema: http://c-faq.com/aryptr/index.html – AnT

+0

pregunta @good para los principiantes ! buddy – niko

Respuesta

2

Wow, eso es un montón de preguntas de una sola vez: P

En primer lugar voy a tratar de explicar esta salida para usted:

4 4 4 
    4 28 4 
    2293536 21 21 

sizeof() es un operador unitario en c. Se reemplaza por un número entero cuando se compila el código, no en tiempo de ejecución. Así que el compilador literalmente cambia sus printfs a:

printf("%d %d %d\n", 4, 4, 4); 
printf("%d %d %d\n", 4, 28, 4); 
printf("%d %d %d",*(&num),*(num),*(&num[0])); 

En una etapa muy temprana de la compilación.

El compilador tiene la amabilidad de darle el tamaño de la matriz completa al escribir sizeof(num). Así es como se define sizeof para trabajar en matrices. Todos los otros elementos le dan el tamaño de un (int *) excepto sizeof (& num) que le da el tamaño de un (int **) (un int ** es del mismo tamaño que un int * de todos modos).

  • & num es la posición de memoria del puntero a la matriz
  • num, y & num [0], es la ubicación de la memoria de la primera int en su conjunto

Para su segunda pregunta;

printf("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s),sizeof(s[0][0]),sizeof(&s)); 

 

sizeof(s[i]) - size of an array (int[2]) == 8 
sizeof(&s[i]) - size of a pointer to an int array sizeof(int **) == 4 
sizeof(s) - size of a 2D array containing 8 ints == sizeof(int[8]) == 32 
sizeof(s[0][0]) - size of an int === 4 
sizeof(&s) - size of a pointer to an array == 4 
3

Sus contradicciones son válidas. Es no el caso que num es equivalente a &num[0]. Eso es simplemente falso. Las matrices son un tipo distinto de punteros, y num se refiere a un objeto con el tipo int[7], no int*. Es por eso que el tamaño es diferente, por ejemplo, porque uno es una colección contigua de siete enteros.

Tenga en cuenta que si el necesario, num se puede convertir en un int*, con el valor &num[0]. Una conversión no es lo mismo que equivalencia, por supuesto. Encontrará esta confusión entre matrices y punteros extrañamente prominente, porque la gente sigue repitiendo la falsedad de que las matrices son punteros. Ellos no son

3

Ahora mi pregunta es si num es idéntica a & num [0] entonces ¿por qué hay una diferencia ahí tamaño?

num es una matriz. sizeof tiene un comportamiento a veces sorprendente para las matrices, que es que te dice el tamaño de almacenamiento de toda la matriz si la pasas una matriz real, pero solo te dice el tamaño de un puntero a un elemento en la matriz si la pasas dirección de tal elemento. Esto puede generar confusión porque el nombre de la matriz se degrada a un puntero en las llamadas a funciones.

Por lo tanto, la respuesta es que num no es idéntica a &num[0] - la última es la dirección del primer elemento de num, con cualquier información sobre el tamaño total de la matriz eliminado.Estas dos cosas son intercambiables en muchos contextos, como llamar a funciones reales, pero no al llamar al sizeof (que no es una función, sino una palabra clave especial manejada por el compilador).

6

Buenas preguntas aquí. Espero que todos podamos explicar estos problemas por usted.

Dada

int num[]={21,22,23,24,25,26,27}; 

Entonces

  • num tiene tipo int[] porque es un array declarado de números enteros cuya memoria se asigna en su lugar. Tenga en cuenta que no tiene el tipo int*, que podría haber sido el caso si lo ha bloqueado.
  • sizeof(num) es 28 porque num es una matriz de 7 pulgadas, que en su máquina son de 4 bytes de tamaño. El valor sería 56 si las entradas tuvieran 8 bytes o 14 si tuvieran 2 bytes, pero 4 bytes por entero es más común.
  • &num[0] es un puntero, del tipo int*, cuyo valor es la dirección del primer elemento de num.
  • Los tamaños de x y sus amigos son 4 porque se declaran como punteros, que en su máquina, en su compilador de C, los punteros se asignan en 4 bytes.

Lo que hay que tener en cuenta es que cuando una matriz se utiliza en ciertos contextos, como ser pasado como parámetro, se convierte a un int*. Es por eso que puede decir *num y obtener 21. Tricky, pero así es como es. Es por eso que generalmente se puede intercambiar num y &num[0], pero realmente debe tener en cuenta la distinción, porque como ha notado, los valores de sizeof son diferentes.

La conversión es por qué y = num tiene sentido. y tiene tipo int* y en C obtiene una conversión automática de int[] A int*. No puede hacer x = &num porque el tipo de &num es "puntero a la matriz int". No puede asignar eso a un int* (puntero a int).

En el caso de

int s [4] [2] = {{1234,56}, {1235,57}, {1236,58}, {1237,59}};

tenemos el tipo de s como int[][], el tipo de &s como pointer to int[][] y el tipo de &s[i] como puntero a int[] (porque s[i] es una matriz int). Debido a la forma en que C le permite asignar/pasar matrices a punteros, puede jugar el mismo tipo de juegos que en su primer ejemplo.

Usted notará que s, &s[0] y &s[0][0] apuntan a las mismas posiciones de memoria, pero, como habrá notado, los sizeof los números serán diferentes.

+0

@pst, bien, hice demasiadas suposiciones. Contiene 7 enteros de cuatro bytes. Sí, el OP podría estar en una máquina con diferentes tamaños de entrada. –

+0

Mejor, y a +1: p –

Cuestiones relacionadas