tipos - que es un arreglo en c++
¿Cuál es exactamente el nombre de la matriz en c? (6)
Me está costando entender el tipo y el uso del nombre de la matriz en C. Puede parecer un post largo, pero por favor tengan paciencia conmigo.
Entiendo que la siguiente declaración declara que a es de tipo int []
ie matriz de enteros .
int a[30];
Mientras que a
también apunta al primer elemento de la matriz y cosas como *(a+2)
son válidas. Por lo tanto, haciendo que parezca un puntero a un número entero . Pero en realidad los tipos int []
e int*
son diferentes; mientras que el primero es un tipo de matriz y más tarde es un puntero a un número entero .
También una variable de tipo int []
se convierte en una variable de tipo int*
cuando la pasa a funciones; como en C
matrices se pasan por referencia (con la excepción del operador sizeof
).
Aquí viene el punto que me hace colgar. Eche un vistazo a la siguiente pieza de código:
int main()
{
int (*p)[3];
int a[3] = { 5, 4, 6 };
p = &a;
printf("a:%d/t&a:%d/n",a,&a);
printf("%d",*(*p + 2));
}
SALIDA:
a:2686720 &a:2686720
6
Entonces, ¿cómo funciona el código anterior? Tengo dos preguntas:
-
a
y&a
tienen los mismos valores. ¿Por qué? - ¿Qué es exactamente
int (*p)[3];
¿hacer? Declara un puntero a una matriz , lo sé. Pero, ¿cómo es un puntero a una matriz diferente del puntero al primer elemento de la matriz y el nombre de la matriz ?
¿Alguien puede aclarar las cosas? Estoy teniendo muchas confusiones.
Sé que debería usar %p
como marcador de posición en lugar de usar %d
para imprimir el valor de las variables de puntero. Como usar el marcador de posición entero puede imprimir direcciones truncadas. Pero solo quiero mantener las cosas simples.
- a y & a tienen los mismos valores. ¿Cómo?
Tienen el mismo valor pero diferentes tipos. Los objetos de matriz no tienen relleno entre los elementos (antes o después), por lo que la dirección de la matriz y la dirección del primer elemento de la matriz son las mismas.
Es decir:
(void *) a == (void *) &a
- ¿Qué es exactamente lo que hace int (* p) [3]; Declara un puntero a una matriz, lo sé. Pero, ¿cómo un puntero a una matriz es diferente del puntero al primer elemento de la matriz y el nombre de la matriz?
Estos son dos tipos de punteros diferentes. Tomemos como ejemplo la aritmética del puntero:
a + 1 /* address of the second element of the array */
&a + 1 /* address one past the last element of the array */
EDITAR: debido a la demanda popular agregué a continuación cierta información sobre la conversión de matrices.
Con tres excepciones, en una expresión, un objeto de tipo matriz de T
se convierte a un valor de tipo puntero a T
apunta al primer elemento de la matriz. Las excepciones son si el objeto es el operando de sizeof
o &
unary operator o si el objeto es una cadena literal que inicializa una matriz.
Por ejemplo, esta declaración:
printf("a:%d/t&a:%d/n", a, &a);
es en realidad equivalente a:
printf("a:%d/t&a:%d/n", &a[0], &a);
También tenga en cuenta que d
especificador de conversión solo se puede usar para imprimir un entero con signo; para imprimir un valor de puntero, debe usar el especificador p
(y el argumento debe ser void *
). Entonces, para hacer las cosas correctamente, use:
printf("a:%p/t&a:%p/n", (void *) a, (void *) &a);
respectivamente:
printf("a:%p/t&a:%p/n", (void *) &a[0], (void *) &a);
- a corresponde al puntero apuntando al 0 ° elemento de la matriz. Mientras que, el mismo es el caso con & a.It acaba de dar la dirección de inicio de la matriz.
Como, a --> pointer pointing to starting element of array a[],it does not know about other element''s location.
.
&a --->address location for storing array a[] which stores first element location,but knows every element''s location
.
Del mismo modo, la ubicación de otros elementos será (a + 2), (a + 4) y así hasta el final de la matriz.
Por lo tanto, obtuviste ese resultado.
- int (* p) [3] es un puntero a la matriz. si hubiera sido int * p [3], significaría completamente diferente. Hubiera significado una serie de indicadores que hubieran sido totalmente diferentes de este contexto.
El puntero a una matriz se ocupará automáticamente de todos los demás elementos de la matriz. En este caso, el suyo es (p);
Mientras que, el puntero al primer elemento de la matriz, es decir, a solo conocerá el primer elemento de la matriz. Tendrá que dar manualmente las direcciones aritméticas del puntero para acceder a los siguientes elementos. Vea, en este caso --- podemos obtener el segundo elemento de a añadiendo 2 a a, es decir, un + 2, tercer elemento sumando 4 a a, es decir, a + 4 y así sucesivamente. // ¡tenga en cuenta la diferencia de dos ya que es una matriz de enteros!
De C99 Norma n1124 6.3.2.1 p3
Excepto cuando es el operando del operador sizeof o el operador unario, o es un literal de cadena usado para inicializar una matriz, una expresión que tiene el tipo '''' matriz de tipo '''' se convierte en una expresión con el tipo '''' puntero a escriba '''' que apunta al elemento inicial del objeto array y no es un valor l. Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento no está definido.
En respuesta a la pregunta 1, este es simplemente un aspecto del lenguaje C tal como está diseñado; a diferencia de la mayoría de los otros lenguajes modernos, C / C ++ permite la manipulación directa de direcciones en la memoria y ha incorporado instalaciones para ''comprender'' eso. Hay muchos artículos en línea que explican esto mejor de lo que pude en este pequeño espacio. Aquí hay una y estoy seguro de que hay muchas otras: http://www.cprogramming.com/tutorial/c/lesson8.html
a y & a tienen el mismo valor porque hace mucho tiempo se requería que usas el operador de dirección & en las matrices para obtener la dirección de la matriz, pero ya no es necesario. El nombre de la matriz (a en este caso) en estos días solo representa la dirección de memoria de la matriz en sí, que también es lo que obtienes de & a. Es una forma abreviada que el compilador maneja para ti.
Otras respuestas ya explicaron el problema. Estoy tratando de explicarlo con un diagrama. Espero que esto ayude
Cuando declaras una matriz
int a[3] = {5, 4, 6}
la disposición de memoria se ve como
Ahora respondiendo tu pregunta:
a
y&a
tienen los mismos valores. ¿Cómo?
Como ya sabe, a
es de tipo de matriz y nombre de matriz a
convierte en un puntero al primer elemento de la matriz a
(después de la descomposición), es decir, apunta a la dirección 0x100
. Tenga en cuenta que 0x100
también es la dirección de inicio del bloque de memoria (matriz a
). Y debe saber que, en general, la dirección del primer byte se dice que es la dirección de la variable . Es decir, si una variable es de 100 bytes, su dirección es igual a la dirección de su primer byte.
&a
es la dirección de todo el bloque de memoria, es decir, es una dirección de la matriz a
. Ver el diagrama:
Ahora puede entender por qué a
&a
y &a
tienen el mismo valor de dirección aunque ambos son de tipo diferente.
¿Qué es exactamente lo que hace
int (*p)[3];
Declara un puntero a una matriz, lo sé. Pero, ¿cómo un puntero a una matriz es diferente del puntero al primer elemento de la matriz y el nombre de la matriz?
Vea la figura anterior, se explica claramente cómo el puntero a una matriz es diferente del puntero a un elemento de la matriz.
Cuando asigna &a
a p
, p
apunta a toda la matriz que tiene una dirección de inicio 0x100
.
NOTA: En cuanto a la línea
... como en
C
arreglos se pasan por referencias (a excepción delsizeof
función).
En C, los argumentos se pasan por valor. No pasa por referencia en C. Cuando se pasa una variable ordinaria a una función, se copia su valor; cualquier cambio al parámetro correspondiente no afecta la variable.
Las matrices también se pasan por valor, pero la diferencia es que el nombre de la matriz se desvía al puntero al primer elemento y este puntero se asigna al parámetro (aquí se copia el valor del puntero) de la función; la matriz en sí no está copiada.
A diferencia de la variable ordinaria, una matriz utilizada como argumento no está protegida contra ningún cambio, ya que no se realiza ninguna copia de la matriz , sino que se realiza una copia del puntero al primer elemento.
También debe tener en cuenta que sizeof
no es una función y el nombre de la matriz no actúa como argumento en este caso. sizeof
es un operador y el nombre de la matriz sirve como un operando . Lo mismo es cierto cuando el nombre de la matriz es un operando del operador unario.