¿Qué es `int * máscara de usuario?[3][4]` apuntando a?

6 minutos de lectura

¿Que es int mascara de usuario34 apuntando a
Tim

Estoy modificando un código y encontré una declaración que tengo problemas para entender:

int *userMask[3][4] = {0};

¿A qué apunta exactamente esto? ¿Es una matriz donde cada elemento es un puntero? ¿O está apuntando a una matriz de tamaño [3][4]?

Gracias


Supongo que mi pregunta es cómo userMask[2][maskElement][user] puede funcionar cuando se declara como int. ¿No tendría que ser userMask int[] para que funcione correctamente? No debo estar entendiendo esto bien…

En una nota al margen, gracias por su sugerencia sobre cdecl Robert. Sin embargo, ¿alguien sabe cómo usarlo en un símbolo del sistema de XP? Todo lo que puedo obtener es un error de sintaxis 🙁

¿Que es int mascara de usuario34 apuntando a
Johannes Schaub – litb

Respuesta corta

Dado que userMask se declara como

int *userMask[3][4];

luego userMask tiene tipo int*[3][4]. Es una matriz 2d de punteros a int. El tamaño de la dimensión exterior es 3, el tamaño de la dimensión interior es 4. Realmente eso no es más que una matriz 1d de 3 elementos cuyo tipo de elemento es otra matriz 1d de 4 elementos cuyo tipo de elemento es int*.

Pasos explicados

entonces si lo haces

userMask[2][maskElement][user]

luego, esencialmente, con los dos primeros índices, selecciona el puntero particular de la matriz 2d:

int * p = userMask[2][maskElement];

luego eliges un int en algún lugar desplazado de ese puntero haciendo

p[user]

ahora ese código está todo adentro userMask[2][maskElement][user].

Código C válido

Para hacerlo paso a paso con un código c válido (no se preocupe si aún no entiende todo lo siguiente):

int * userMask[3][4] = { { 0 } };
int ** pa = userMask[2]; /* int*[4] becomes int** implicitly */
int * pi = pa[maskElement];
int i = pi[user];

assert(i == userMask[2][maskElement][user]);

Diferencia entre matrices y punteros

Así que creo que te muestro algo importante. La matriz de arriba hace no contienen punteros a matrices. Veamos qué tan diferentes se comportan, lo que muchos programadores de C no esperan:

int array[5][4][3];
/* int[4][3] implicitly converts to int(*)[3] (pointer to first element) */
int (*parray)[3] = array[0]; 
int ** pint = (int**) array[0]; /* wrong!! */

Ahora, ¿qué pasará si hacemos parray[1] y pint[1] ? El primero avanzará parray por sizeof(int[3]) bytes (3 * sizeof(int)), el segundo avanzará sólo sizeof( int* ) bytes Entonces, en realidad, mientras que el primero te da la matriz correcta array[0][1]el segundo te dará ( char * )array[0] + sizeof( int* ), que es un lugar en el que realmente no queremos que esté. Pero agarrar el desplazamiento incorrecto no se trata solo de eso. Debido a que no sabe que se accede a una matriz, intentará interpretar lo que hay en pint[1] como un int*. Digamos que su matriz se inicializó con 0x00. Luego hará el siguiente paso de índice basado en la dirección 0x00 (Haciendo pint[1][0] por ejemplo). ¡Oh, no, comportamiento completamente indefinido! Así que es muy importante enfatizar la diferencia.

Conclusión

Esto fue más de lo que pediste, pero creo que es muy importante conocer estos detalles. Especialmente si desea pasar matrices 2D a funciones, este conocimiento es realmente útil.

  • Si ese es el caso, todavía estoy un poco confundido. La matriz userMask se usará más adelante como: if(userMask[2][maskElement][user] && bla) resultado = verdadero; ¿Cómo se puede hacer referencia a ese puntero a un int por [user] ¿Me gusta esto? No es una matriz int, es un int, ¿correcto?

    – Tim

    8 de noviembre de 2008 a las 16:17

  • El OP preguntó por C, no por C++.

    – Roberto Gamble

    8 de noviembre de 2008 a las 17:55

  • ups, no me había dado cuenta. lo siento, leeré con más cuidado la próxima vez 🙂

    – Johannes Schaub – litb

    8 de noviembre de 2008 a las 17:58

1647577208 603 ¿Que es int mascara de usuario34 apuntando a
cristian

Esta es una matriz bidimensional donde cada elemento es un puntero a un inty todos los punteros se inicializan a cero.

En su seguimiento, muestra que la matriz se usa así:

if(userMask[2][maskElement][user] && blah)
    result = true;

En este caso, cada elemento de userMask en realidad debería apuntar a una matriz de ints. (Un int* puede apuntar a un solo int o una matriz de ints). Para determinar esto, verifique el código que asigna valores a userMask. Por ejemplo, es posible escribir:

int userArray[2] = { 10, 20 };

userMask[0][0] = userArray; // userMask[0][0] points to the
                            // first element of userArray.

Luego, el siguiente código se indexa en userArray:

int value = userMask[0][0][1]; // sets value = userArray[1], giving 20.

1647577209 322 ¿Que es int mascara de usuario34 apuntando a
roberto apuesta

int *userMask[3][4] = {0};

es una matriz bidimensional donde cada miembro es un puntero a int. Además, todos los miembros se inicializan en punteros nulos.

int (*userMask)[3][4];

sería un puntero a una matriz bidimensional de enteros. Los corchetes en C se unen más que *, por lo que los paréntesis son necesarios para crear un puntero a una matriz.

cdecl es una utilidad simple que puede descargar para explicar declaraciones complejas:

cdecl> explain int *userMask[3][4]
declare userMask as array 3 of array 4 of pointer to int

También puede hacer lo contrario:

cdecl> declare userMask as pointer to array 3 of array 4 of int
int (*userMask)[3][4]

  • Todos los miembros son nulos sin inicialización. Todos los miembros se inicializan a 0. Hay una diferencia, incluso si es muy buena.

    – tloach

    8 de noviembre de 2008 a las 16:54

  • @tloach, lo siento, pero nada de lo que dijiste tiene sentido para mí. C no inicializa automáticamente las variables a menos que sean estáticas y no sé cuál crees que es la diferencia entre inicializar punteros a 0 o nulos, pero no hay ninguno.

    – Roberto Gamble

    8 de noviembre de 2008 a las 16:59

if(userMask[2][maskElement][user] && blah)
   result = true;

La segunda parte aquí es que no hay arreglos en C; sólo hay aritmética de punteros. Por definición, p[i] siempre es equivalente a *(p+i) entonces

userMask[2][maskElement][user]

es equivalente a

*((userMask[2][maskElement])+user)

El código está en alguna parte asignando un vector (apuesto a que es de malloc(3c) o una llamada similar) al puntero en esa matriz; ahora tu si esta diciendo

SI el elemento user-th del vector en userMask[2][maskElement] es distinto de cero

ENTONCES SÍ bla no es cero (debido a la evaluación de cortocircuito de &&, el segundo conjunto no se evalúa si el primer conjunto es 0)

LUEGO establecer resultado = verdadero.

1647577210 166 ¿Que es int mascara de usuario34 apuntando a
charlie martin

Aplicar la regla de adentro hacia afuera.

int *userMask[3][4] = {0};

Comenzando en la parte interior de la declaración,

userMask

es el nombre

userMask[3] 

asigna espacio para (es un vector de) 3 de ellos

userMask[3][4] 

asigna espacio para 4 userMask[3]‘s

int *

nos dice que userMask los elementos son de tipo puntero a int

y luego = {0} es un inicializador donde todos los elementos son 0. Entonces

int *userMask[3][4] = {0};

es una matriz de 3×4 de int *, inicializada en 0.

¿Que es int mascara de usuario34 apuntando a
cameron

Creo que esa declaración accede a la tercera fila de la matriz de máscaras de usuario, luego accede al puntero maskElement’th en esa fila, y dado que es un puntero int, puede apuntar al comienzo de una matriz int (piense en cadenas de caracteres), que yo suponga que lo está haciendo, y esa matriz está subindexada por el usuario.

1647577211 423 ¿Que es int mascara de usuario34 apuntando a
pdc

userMask[2] es de tipo int*[],
userMask[2][maskElement] es de tipo int*,
y entonces userMask[2][maskElement][user] es de tipo int.

La declaracion

int *userMask[3][4] = {0};

es una abreviatura de

int *userMask[3][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};

donde cada uno de los ceros se convierte implícitamente en (int*)0.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad