Las matrices y los punteros no son lo mismo en C, aunque están relacionados y pueden usarse de manera similar. Hasta ahora todos estamos de acuerdo.
Sin embargo, no veo por qué se incluyeron matrices en C, cuando los punteros podrían haber hecho su trabajo perfectamente.
No estoy diciendo que elimine la notación de matriz (por ejemplo, a [5] o int a [4] = {0,1,2,3};), que es bastante útil y conveniente. Pero podría tener esa misma notación trabajando sobre punteros (como es el caso), como una medida cosmética. Entonces, la notación de matriz no es una razón para tener matrices, ¡solo la notación!
La única diferencia que veo es que las matrices son punteros constantes, y el tamaño de la memoria a la que apuntan no se puede cambiar. Pero esto también se puede lograr con punteros, exactamente haciéndolos constantes (la memoria no sería de tamaño fijo, pero no estoy seguro de si esto es un problema).
Entonces, ¿por qué no tener solo punteros y dejar que el programador decida cómo debe comportarse el puntero (es decir, constante, no constante, tamaño fijo, tamaño variable, etc.)?
x = a + b * 2;
cuando podrías lograr lo mismo con una secuencia de expresiones simples comox = b; x*=2; x+=a;
?Respuestas:
Las matrices son memorias contiguas creadas en la pila. No puede garantizar una memoria de pila contigua sin este azúcar sintáctico, e incluso si pudiera, tendría que asignar un puntero separado para poder hacer la aritmética del puntero (a menos que quisiera hacerlo
*(&foo + x)
, lo cual no soy claro, pero podría violar la semántica del valor l, pero al menos es bastante incómodo, y gritaría por algún tipo de azúcar sintáctico). En cuanto al diseño, también es una forma de encapsulación, ya que puede referirse a la colección con un solo identificador (que de lo contrario requeriría un puntero separado). E incluso si pudiera asignarlos contiguamente y asignar un puntero separado para hacer referencia a ellos, tendría cualquieraint fooForSomething, fooForSomethingElse
... lo que fuerza una gran cantidad de creatividad a medida que su colección crece, por lo que podría pensar en simplificar conint foo1, foo2
..., que se parece a una matriz pero es más difícil de mantener.fuente
static
s) generalmente termina en otro lugar dependiendo del entorno.La notación de matriz es conveniente, más fácil de leer y menos propensa a errores. Proporciona un formalismo sobre punteros. Puede ser azúcar sintáctico, pero todos necesitamos un poco de dulzura de vez en cuando, ¿no?
Al igual que con todas las abstracciones, renuncia a un poco de flexibilidad para la comodidad que brinda la abstracción.
fuente
Me sorprende que nadie haya comentado nada sobre las matrices multidimensionales todavía.
Si tiene una matriz hecha de "punteros anidados" (digamos
int **p
), lo que tiene en cada "fila" (dimensión exterior) es un puntero que apunta al primer elemento de esa fila, por lo que acceder a un valor requiere dos accesos de memoria. Además, la memoria que requiere essizeof(*int)*n + n*m*sizeof(int)
.En el escenario de matriz bidimensional
int p[n][m]
, el acceso a un elemento requiere solo un acceso a la memoria, porque la dirección de la fila se calcula en lugar de buscarla; y la memoria requerida es sólon*m*sizeof(int)
.Otro lugar donde una matriz no puede ser reemplazada por un puntero es dentro de las estructuras.
definitivamente no es lo mismo que
El tamaño de la matriz es importante allí, y los punteros no tienen esa información.
Entonces, sí, las matrices unidimensionales y los punteros individuales son en su mayoría intercambiables, pero sus similitudes terminan allí.
fuente
i,j
pori*cols+j
, pero creo que al no tener que hacerlo solo es una razón suficientemente buena para justificar la existencia de tipos de matriz.¿Por qué querría no poder usar matrices para tipos de valor?
int a[4] = {0,1,2,3};
fuente
¿Cómo manejaría plataformas, como la 8031 sin memoria externa, que no admiten
malloc
oalloca
? Quizás se esté olvidando de que C no es solo para hierro grande, sino también para controladores de elevadores y tostadoras.fuente
En C, la notación de matriz dentro de las expresiones siempre es simplemente aritmética de puntero. Todos los usos de un identificador de matriz en una expresión se convierten inmediatamente de "matriz de T" a "puntero a T" y el valor se convierte en un puntero al primer elemento de la matriz. La notación de matriz (por ejemplo
a[1][2]
) siempre se expande en aritmética de puntero (por ejemplo*(*(t+1)+2)
).Sin embargo, la notación de matriz en declaraciones y definiciones es algo completamente distinto. Un declarador matriz describe un "array de T de tipo" donde los valores de este tipo son secuencias de elementos de tipo T . La definición de un objeto de matriz tiene que ver con el uso de una notación de matriz conveniente y fácil de entender para asignar la cantidad adecuada de almacenamiento para la matriz de objetos deseada de modo que el identificador de matriz se refiera a este almacenamiento sin que parezca un puntero. En efecto, la notación de matriz en una declaración o definición es una macro que genera una expresión usando
sizeof()
y aritmética, y en el caso de una definición, el equivalente dealloca()
para arreglos automáticos o su equivalente en el vinculador para arreglos globales, y hacerlo todo en tiempo de compilación (bueno, excepto para arreglos de longitud variable C99).El uso de la notación de matriz en expresiones y el uso de tipos de matriz no está tan estrechamente conectado, aunque es tradición y modismo usar la notación de matriz en expresiones para hacer referencia al almacenamiento en objetos declarados y / o definidos como matrices. Puede usar la notación de matriz con un tipo de puntero para hacer que la aritmética del puntero sea más limpia y significativa. De hecho, en C una expresión de la forma
e1[e2]
es precisamente equivalente a la expresión*((e1)+(e2))
. La conversión binaria habitual se aplica a los dos operandos, y el resultado es siempre un valor l . Como el operador de indirección (*
) debe tener un puntero como su operando, uno dee1
ye2
debe ser un puntero y el otro debe ser un entero, pero no importa cuáldado que la conversión unaria inicial para cualquier "matriz de T" es convertirla en "puntero a T". La notación de matriz en expresiones es en efecto una macro compiladora (nivel de lenguaje) para generar expresiones aritméticas de puntero.Entonces, realmente C ya funciona de la manera que sugieres, pero estás confundiendo el uso de la notación en dos contextos muy separados.
fuente