2009-09-03 6 views

Respuesta

16

En caso de duda - pida cdecl

$> cdecl 
Type `help' or `?' for help 
cdecl> explain int *columns[32] 
declare columns as array 32 of pointer to int 

EDITAR En respuesta a los comentarios: He encontrado la fuente cdecl en Google Code Search. Requiere la biblioteca GNU readline. Creo que no debería ser un problema compilarlo en Mac OS X o Windows.

+3

Por curiosidad, ¿sabes dónde conseguir 'cdecl'? Los cerdos capitalistas de Apple no tuvieron la amabilidad de proporcionarle sus herramientas de desarrollo. –

+0

+1 señor, nunca antes había visto esa herramienta, leyendo la página del manual ahora ... –

+0

@Chris Mac OS X no incluye cdecl? Pensé que es una herramienta estándar para todos los Unixes. Puede tomar la fuente cdecl de cualquier distribución de Linux y compilarla en Mac OS X. No creo que tenga ninguna dependencia (bueno, tal vez readline) – qrdl

0

Un programa de prueba es ilustrativa, especialmente a aquellos de nosotros que no son abogados idioma:

$ gcc -x c - 
#include <stdio.h> 

int main(void) 
{ 
    int *columns[32]; 
    printf("%lu\n%lu\n", sizeof(columns), sizeof(columns[0])); 
    return 0; 
} 
$ ./a.out 
128 
4 
$ 

que parece ser una matriz de punteros.

+1

No me gustaría decir que entender las declaraciones requiere el estado de "abogado de idiomas". – GManNickG

+0

Lo sé, pero nunca podría recordar cuál era, y OS X no tiene una buena versión de 'cdecl' instalada. –

+0

La mayoría de los que no son abogados no podrían decirle qué 'void (* (* (* p) [N] [M]) [O]) (char c) = 0;' declara sin usar 'cdecl' o 'geordi' u otras trampas, creo. –

7

Usted está definiendo una matriz de 32 punteros.

Para definir un puntero a un array de 32 enteros que tiene que hacer

int (*columns)[32]; 

La declaración anterior crea una instancia de una matriz con espacio para 32 * sizeof (int). Por otra parte, esta última instancia un único puntero no inicializado que luego se puede utilizar de la siguiente manera:

int myintegers[32] = {0, 1, 2, ..., 31}; 
int (*columns)[32]; 

columns = &myintegers; 

printf("%d\n", (*columns)[2]); 

espero haber dejado la diferencia un poco clara.

+0

lo hizo, gracias –

5

Es una matriz de 32 punteros a int y sí, sí importa.

reglas gramaticales El C especifican que array de acceso ([]) se une más apretado que dereference (*) y declaraciones espejo uso.

La declaración int *columns[32]; significa que la expresión *columns[n] (donde n es un número entre 0 y 31) es una int. Esta expresión es la misma que *(columns[n]). La declaración asigna el espacio para 32 punteros, pero no hay int s asignados y (suponiendo que se trate de una declaración local de función) ninguno de los punteros se inicializa.

Tenía la declaración ha sido int (*columns)[32]; entonces la expresión (*columns)[n] habría sido una int, lo que significa que el * eliminar la referencia ocurre antes de que el acceso a la matriz, por lo que las columnas habrían sido un puntero a un array de 32 int s. La declaración debería haber asignado un puntero, pero no matrices de int s.

+0

No soy muy usuario de C/C++, pero el idioma me interesa. Esto parece algo contrario a la intuición, tal vez porque vengo de un fondo de C#. Si declara int (* columns) [32], esperaría que obtenga una matriz de 32 punteros. Lo percibo de tal manera que la expresión entre paréntesis especifica un tipo de puntero, y el especificador de matriz significa "32 instancias del tipo a la izquierda". Por lo tanto, 32 punteros. Lo mismo ocurre a la inversa: si dices int * columnas [32] y los corchetes se unen más, la forma intuitiva es una matriz de 32 elementos y luego un puntero a ella. –

+0

¿Por qué es al revés? También he visto la sintaxis de paréntesis en otros lugares, sobre todo los punteros de función. Y tampoco tiene sentido para mí allí. ¿Cómo debería pensarlo para que tenga sentido? –

+0

K & R son probablemente más adecuados para responder 'por qué'. :) Estoy de acuerdo con tu intuición, sin embargo. –

0

Un truco es leer De derecha a izquierda.

Given int * cols [32];

  1. ves por primera vez cols [32]: esta es una matriz de tamaño 32.
  2. siguiente que ver int *: este es un puntero

Todo lo que queda de matriz es el tipo de los elementos en la matriz. Entonces lo leemos como una matriz de punteros a int (y del recuento 32).

20

Ampliando un comentario a otra respuesta:

Hay un procedimiento bastante sencillo para la lectura de declaraciones de C. Comience con el identificador situado más a la izquierda en el declarador y continúe su camino de salida, recordando que [] y () se enlazan antes de *. Teniendo en cuenta la declaración

int *columns[32]; 

ruptura hacia abajo como

 columns     -- columns 
    columns[32]    -- is a 32-element array 
    *columns[32]    -- of pointers 
int *columns[32]    -- to int. 

Si la declaración había sido

int (*columns)[32]; 

entonces se rompería como

 columns     -- columns 
    (*columns)    -- is a pointer 
    (*columns)[32]   -- to a 32-element array 
int (*columns)[32]   -- of int. 

Esto también ayudará usted construye decl complejo araciones. Suponga que desea declarar una matriz de punteros a funciones que devuelven punteros a las matrices de carbón:

  f      -- f 
      f[N]     -- is an N-element array 
     *f[N]     -- of pointers 
     (*f[N])()    -- to functions 
     *(*f[N])()    -- returning pointers 
     (*(*f[N])())[M]   -- to M-element arrays 
    *(*(*f[N])())[M]   -- of pointers 
char *(*(*f[N])())[M];   -- to char 

cdecl es una buena herramienta, pero después de que había hecho este ejercicio un par de veces, no lo necesita.

+1

Me gusta mucho esta respuesta –

+1

Esta es una respuesta en la que deseo que StackOverflow tuviera una función de "Respuesta favorita". : -/puntaje + = 1; –

0

refiérase a la pregunta # 5 de A 'C' Test: The 0x10 Best Questions for Would-be Embedded Programmers por Nigel Jones *


a) int a; // Un entero

b) int * a; // Un puntero a un entero

c) int ** a; // Un puntero a un puntero a un entero

d) int a [10]; // Una matriz de 10 enteros

e) int * a [10]; // Una matriz de 10 punteros a enteros

f) int (* a) [10]; // Un puntero a una matriz de 10 enteros

g) int (* a) (int); // Un puntero a una función a que toma un argumento entero y devuelve un entero

h) int (* a [10]) (int); // Una serie de 10 punteros a funciones que toman un argumento entero y devuelven un entero


* Por desgracia, el artículo original en embedded.com ya no se puede conocer en su página web.

Cuestiones relacionadas