C puntero a matriz / matriz de punteros desambiguación


¿Cuál es la diferencia entre las siguientes declaraciones:

int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);

¿Cuál es la regla general para entender declaraciones más complejas?

Author: akashchandrakar, 2009-05-13

12 answers

int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers

El tercero es el mismo que el primero.

La regla general es precedencia del operador. Puede conseguir incluso mucho más complejo como punteros de función entran en la imagen.

 402
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 18:37:30

Utilice el programa cdecl , como sugiere K & R.

$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>

También funciona al revés.

cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
 249
Author: sigjuice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-03 14:47:04

No se si tiene un nombre oficial, pero lo llamo the Right-Left Thingy(TM).

Comience en la variable, luego vaya a la derecha, a la izquierda y a la derecha...y así sucesivamente.

int* arr1[8];

arr1 es una matriz de 8 punteros a enteros.

int (*arr2)[8];

arr2 es un puntero (el paréntesis bloquea la derecha-izquierda) a una matriz de 8 enteros.

int *(arr3[8]);

arr3 es una matriz de 8 punteros a enteros.

Esto debería ayudarle con declaraciones complejas.

 118
Author: GManNickG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 18:41:48
int *a[4]; // Array of 4 pointers to int

int (*a)[4]; //a is a pointer to an integer array of size 4

int (*a[8])[5]; //a is an array of pointers to integer array of size 5 
 24
Author: Sunil bn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-20 16:19:14

La respuesta para los dos últimos también se puede deducir de la regla de oro en C:

La declaración sigue al uso.

int (*arr2)[8];

¿Qué sucede si dereference arr2? Se obtiene una matriz de 8 enteros.

int *(arr3[8]);

¿Qué sucede si tomas un elemento de arr3? Se obtiene un puntero a un entero.

Esto también ayuda cuando se trata de punteros a funciones. Para tomar el ejemplo de sigjuice:

float *(*x)(void )

¿Qué sucede cuando desreferencia x? Se obtiene una función que se puede llamar sin argumentos. ¿Qué pasa cuando lo llamas? Devolverá un puntero a un flotador.

La precedencia del operador siempre es complicada, sin embargo. Sin embargo, usar paréntesis también puede ser confuso porque la declaración sigue al uso. Al menos, para mí, intuitivamente arr2 parece una matriz de 8 punteros a ints, pero en realidad es al revés. Solo toma un tiempo acostumbrarse. Razón suficiente para agregar siempre un comentario a estas declaraciones, si se pregunta me:)

Editar: ejemplo

Por cierto, me topé con la siguiente situación: una función que tiene una matriz estática y que usa aritmética de puntero para ver si el puntero de fila está fuera de los límites. Ejemplo:

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

#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))

int *
put_off(const int newrow[2])
{
    static int mymatrix[3][2];
    static int (*rowp)[2] = mymatrix;
    int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);

    memcpy(rowp, newrow, sizeof(*rowp));
    rowp += 1;
    if (rowp == border) {
        rowp = mymatrix;
    }

    return *rowp;
}

int
main(int argc, char *argv[])
{
    int i = 0;
    int row[2] = {0, 1};
    int *rout;

    for (i = 0; i < 6; i++) {
        row[0] = i;
        row[1] += i;
        rout = put_off(row);
        printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
    }

    return 0;
}

Salida:

0 (0x804a02c): [0, 0]
1 (0x804a034): [0, 0]
2 (0x804a024): [0, 1]
3 (0x804a02c): [1, 2]
4 (0x804a034): [2, 4]
5 (0x804a024): [3, 7]

Tenga en cuenta que el valor de border nunca cambia, por lo que el compilador puede optimizar eso. Esto es diferente de lo que inicialmente podría querer usar: const int (*border)[3]: que declara border como un puntero a una matriz de 3 enteros que no cambiará el valor mientras exista la variable. Sin embargo, ese puntero puede apuntar a cualquier otra matriz de este tipo en cualquier momento. Queremos ese tipo de comportamiento para el argumento, en su lugar (porque esta función no cambia ninguno de esos enteros). La declaración sigue al uso.

(p. s.: ¡siéntase libre de mejorar esta muestra!)

 14
Author: Hraban Luyat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-30 13:21:00
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
 5
Author: Byron Formwalt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-14 17:51:34

Creo que podemos usar la regla simple ..

example int * (*ptr)()[];
start from ptr 

" ptr es un puntero a " ve hacia la derecha ..su") " ahora ir a la izquierda su a "(" salir ir a la derecha "() " así "a una función que no toma argumentos "go left" y devuelve un puntero "go right" a un array " go left "de enteros"

 2
Author: simal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-09 15:47:56

Como regla general, los operadores unarios derechos (como [], (), etc) tener preferencia sobre los de la izquierda. Por lo tanto, int *(*ptr)()[]; sería un puntero que apunta a una función que devuelve una matriz de punteros a int (obtenga los operadores correctos tan pronto como pueda al salir del paréntesis)

 2
Author: Luis Colorado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-19 13:34:06

Así es como lo interpreto:

int *something[n];

Nota sobre la precedencia: el operador de subíndice de matriz ('[]') tiene mayor prioridad que operador de desreferencia ('*').

Entonces, aquí aplicaremos el '[] 'antes de'*', haciendo la declaración equivalente a:

int *(something[i]);

Nota sobre cómo una declaración tiene sentido: int num significa (num) es un (int), int *ptr o int (*ptr) significa, (valor en ptr) es an (int), que hace de ptr un puntero a int.

Esto se puede leer como, (valor de el (valor en el índice ith del algo)) es un entero. Por lo tanto, (valor en el índice ith de algo) es un (puntero entero), lo que hace que el algo una matriz de punteros enteros.

En el segundo,

int (*something)[n];

Para darle sentido a esta afirmación, usted debe estar familiarizado con este hecho:

Nota sobre la representación de puntero de matriz: SomethingElse [i] es equivalente a *(SomethingElse + i)

Entonces, reemplazando SomethingElse con (*algo), obtenemos * (*algo + i), que es un entero según la declaración. Por lo tanto, (*algo) nos dio una matriz, lo que hace algo equivalente a (puntero a una matriz).

 2
Author: nishantbhardwaj2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-11 18:52:17

Supongo que la segunda declaración es confusa para muchos. Aquí hay una manera fácil de entenderlo.

Permite tener una matriz de enteros, es decir, int B[8].

Vamos a tener también una variable A que apunta a B. Ahora, valor en A es B, es decir, (*A) == B. Por lo tanto A apunta a una matriz de enteros. En su pregunta, arr es similar a A.

De manera similar, en int* (*C) [8], C es un puntero a una matriz de punteros a integer.

 0
Author: nishantbhardwaj2002,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-12 11:46:19

Aquí hay un sitio web interesante que explica cómo leer tipos complejos en C: http://www.unixwiz.net/techtips/reading-cdecl.html

 0
Author: Abhishek Jaisingh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-22 19:51:14

En puntero a un entero si el puntero se incrementa entonces va siguiente entero.

En la matriz de puntero si el puntero se incrementa salta a la siguiente matriz

 -7
Author: Nikhil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-31 14:41:58