C/Matrices: Diferenzas entre revisións

Contido eliminado Contido engadido
Gallaecio (conversa | contribucións)
Sen resumo de edición
Gallaecio (conversa | contribucións)
Revisado.
Liña 1:
{{Navegador|PunteirosMoldes|Cadeas de caracteres}}
 
{| align="right" style="margin-left: 1em;"
Unha matriz (''array'' en inglés) consiste nunha serie de datos ─todos do mesmo [[{{BASEPAGENAME}}/Tipos de datos fundamentais|tipo]]─ almacenados de forma contigua en memoria interna.
| __TOC__
|} <!-- Isto sitúa o índice á dereita -->
 
Unha matriz (''array'' en inglés) consiste nunha serie de datos ─todos do mesmo [[{{BASEPAGENAME}}/Tipos de datos fundamentais|tipo]]─ almacenados de forma contigua en memoria interna.
 
==Declaración==
Ao declararmosdeclarar unha matriz, estamoso declarandoque en realidade se está a facer é declarar un [[{{BASEPAGENAME}}/Punteiros|punteiro]] a un espazo de memoria que conterá os datos dunhada matriz. Dito punteiro estáestará protexido ([[{{BASEPAGENAME}}/Modificadores#const|<codesource lang=c enclose=none>const</codesource>]]), é dicir, non se podepoderá modificar o enderezo de memoria que contén, sempre estará apuntado a dito enderezo.
 
NaA declaración da matriz, supón ademais dun punteiro das características sinaladas no parágrafo anterior, estamos reservandoreservar en memoria estática espazo para unha certa cantidade de elementos do tipo da matriz. EstaAo reservacontrario realízasedo enque memoriapasa cos estática[[{{BASEPAGENAME}}/Punteiros|punteiros]], polono quecaso das matrices será o propio programa quen a xestione (a reserve,memoria aasignada useao epunteiro ada libere),matriz sen necesidade de que sexa o programador quen estableza cando ha de liberarse(reservala, comousala ocorree coa memoria estáticaliberala).
 
==Elementos==
As matrices estás compostas por:
*'''NomeIdentificador'''. É o enderezo simbólico do comezo da matriz na memoria.
*'''Extensión'''. ExpresadoExpresada mediante constantes numéricas enteiras. É a cantidade de celas que hai en cada dimensión da matriz. A extensión non ten por que ser a mesma en todas as dimensións.
*'''Índice'''. Exprésase coma un enteiro ─variable, constante ou expresión de tipo enteiro─ e utilízase para facer referencia a cada unha das celas da matriz.
*'''Dimensións'''. As matrices poden ter unha ou varias dimensións, e segundo o caso o traballo con elas pode variar bastante. A cantidade de dimensións é ilimitada, e establécese sufixando o nome da variable ao declarala con corchetes, unha parella (<code>[]</code>) por cada dimensión, dentro dos cales irá a extensión da dimensión.
Liña 23 ⟶ 27:
 
Onde:
:<code>tipo</code> é un tipo de dato ─ben [[{{BASEPAGENAME}}/Tipos de datos fundamentais|fundamental]], ben [[{{BASEPAGENAME}}#Tipostipo de datos derivados|derivadodato]],
:<code>identificador</code> é o nome ou [[{{BASEPAGENAME}}/Identificadores|identificador]] da matriz, e
:<code>extensión</code> é un número enteiro positivo, a cantidade de celas do tipo de dato da matriz que terá a matriz.
 
Un exemplo de uso podería ser o seguinte:
Liña 31 ⟶ 35:
int notas[6];
</source>
 
Isto provocará que se reserve en memoria interna un bloque de celas, que poderíamos ver coma unha serie de variables do mesmo tipo de dato. O seu tamaño quedará definido en tempo de compilación, o que significa que a <code>extensión</code> non pode ser unha variable, ten que ser unha [[{{BASEPAGENAME}}/Constantes literais|constante literal]].
 
Existen certos casos en que se pode omitir a extensión da matriz unidimensional:
Liña 38 ⟶ 40:
*se se declara coma un parámetro formal nunha función.
 
O tamaño que ocupe en memoria a matriz enteira dependerá do produto do tamaño en bytes do <code>tipo</code> pola <code>extensión</code>. No exemplo queanterior vimossería antes,(<source sería:lang=c enclose=none>sizeof(int)*6</source>) 24 bytes.
<source lang=c>
sizeof(int)*20 = 40 bytes
</source>
 
===''Inicializar'' matrices unidimensionais===
AoSe declararmosao declarar unha matriz, se a inicializamos,''inicializa'' non é necesario especificar a súa extensión, pois esta dedúcese dos valores asignados á matriz. VexamosVéxase o unseguinte exemplo:
<source lang=c>
unsigned short int matriz[]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
</source>
 
O tamaño desta matriz, en celas, sería de 16. En caso de que se queira calcular este valor (o da cantidade de celas) nalgunha parte do programa, poderase deducir dun cálculo sinxelo: dividir o tamaño total da matriz polo tamaño dunha das súas celas. Sirva o seguinte exemplo ─baseado no anterior─ para ilustralo:
<source lang=c>
celas = sizeof(matriz)/sizeof(unsigned short int);
Liña 65 ⟶ 64:
<source lang=c>
notas[0] // Primeira cela
notas[655] // Última cela
</source>
 
Cada cela será coma unha variable do tipo de dato da matriz. Pero cómpre ter en conta que ao contrario que a <code>extensión</code>, o <code>índice</code> dundunha vectormatriz (o que utilizamos para facer referencia a unha cela individual da matriz) pode ser unha variable susceptible de cambiar no tempo de execución. Pero en caso de facelo, haberá que asegurarse de que dito <code>índice</code> non sexa menor que cero nin maior que a <code>extensión</code> menos un, é dicir, un número positivo menor que a <code>extensión</code> ─en caso contrario non se trataría dunha das celas da matriz─.
 
Ao pasarlle a unha [[{{BASEPAGENAME}}/Funcións|función]] unha matriz unidimensional, hai dous datos que temoshai que pasarlle como mínimo á función: o enderezo da matriz e maila súa extensión (ou a extensión da parte da matriz que na práctica vai utilizar a función).
 
Nótese que pasarlle unha matriz a unha función equivale a un [[{{BASEPAGENAME}}/Funcións#Paso por valor e paso por referencia|paso por referencia]] dende oun punto de vista global. É dicir, pásanselle á función dous datos, un por valor (a extensión da matriz) e outro por referencia (o enderezo da matriz). Isto resulta nunha función que non traballa cunha copia local (local para a función) da matriz, senón coa matriz orixinal, e os cambios nela afectarán a todas as funcións do programa, incluída a principal. Nalgúns casos quizais sexa mellor declarar na función outra matriz para copiar nela os datos da matriz orixinal e traballar con elesela sen modificar a matriz orixinal.
 
Para enviarlle a unha función o enderezo dunha matriz, faise prefixando o identificador da matriz co símbolo[[{{BASEPAGENAME}}/Operadores#Enderezo|operador de enderezo]], «<code>&</code>» (paso por referencia) na chamada á función, e sufixándoo co número da primeira cela da matriz (<code>[0]</code>). VexamosA súa sintaxe sería una exemploseguinte:
<source lang=c>
funcionfunción(&matriz[0],extensionextensión);
</source>
 
Para simplificar as cousas, cómpre ter en conta algo que non se comentou ata agora: o identificador dunha variable equivale ao enderezo na memoria da súa primeira cela. É dicir, o exemplo anterior tería o mesmo efecto que o seguinte:
<source lang=c>
funcionfunción(matriz,extensionextensión);
</source>
 
E na cabeceira da [[{{BASEPAGENAME}}/Funcións#Definición dunha funcións|definición da función]] declárase o enderezo de memoria da matriz recibido comomediante uno punteiro,[[{{BASEPAGENAME}}/Operadores#Apuntado|operador éde dicirapuntado]], precedéndoo dun asterisco: «<code>*</code>». ParaA osúa exemplo,sintaxe quedaría unha definiciónfundamental comosería a seguinte:
<source lang=c>
función(*matriz,extensión){
int funcion(int *matriz,int extension) // Os tipos de dato, así coma os identificadores, son só de exemplo.
// [...]
{
...
}
</source>
 
Ás veces pode resultar útil mandarlle a unha función unha matriz mentíndolle sobre onde comeza. É dicir, mandarlle a unha función unha matriz especificando dende que parte ten que lela. Para iso, cambiaremoscámbiase a cela inicial (<code>[0]</code>) por calquera outra. No seguinte exemplo, chamaremos á función de xeito que interprete a matriz dende a terceira cela e ata a oitava:
<source lang=c>
funcionfunción(&matriz[2],7); // Compre lembrar que se comeza a conta das celas dende 0, non dende 1
</source>
 
==Matrices bidimensionaisde dúas dimensións==
As celas das matrices poden repartirse en distintas dimensións para facilitar a visualización dos datos que contén ou o traballo con elas. En realidade, as celas dunha matriz en varias dimensións gárdanse en memoria do mesmo xeito que as matrices unidimensionais. De feito, pódese traballar cunha matriz de varias dimensións coma se en realidade tivese unha única dimensión.
 
DeAínda feitomáis, podepodería darse o caso de que segundo a parte dodun programa naen que esteamos,se comprirátraballe utilizarde axeito distinto ─cunha matriz comacomo se tivese unha dimensións ou coma se tivese as que en realidade tenten─ segundo a parte do programa de que se trate.
 
Cómpre ter en conta que ao pasarlle unha matriz de varias dimensións a unha función docomo xeito quese vimosfai parano ascaso matricesdas dunha sóasoa dimensión, en principio teremosterase que traballar coa matriz coma se tivese unha sóasoa dimensión. Isto supón que sexa preciso calcular previamente o valor do índice para as celas. No caso dunha matriz de dúas dimensións, isto resulta unha tarefa bastante doada de realizar:
 
:<code>extensión da segunda dimensión * lugar da cela na primeira dimensión + lugar da cela na segunda dimensión</code>
Liña 129 ⟶ 127:
A extensión das dimensións adicionais (a partires da primeira) non pode fornecérselle á función de forma dinámica. É unha constante literal, e simplemente teremos que asegurarnos de que o seu valor é grande abondo para as distintas matrices que se lle podan fornecer á función, pois á hora da verdade os límites veñen establecidos por variables fornecidas á función, no exemplo anterior: <code>filas</code> e <code>columnas</code>, que serían a extensión real das dimensións primeira e segunda da matriz, respectivamente.
 
As extensións que necesariamente temos que especificar ao definir a función (as das dimensións adicionais), que abonda con que sexan superiores ás reais de cada caso, podemos controlalas mediante [[{{BASEPAGENAME}}/ConstantesDirectrices simbólicas#definepara o preprocesador|directrices <codesource lang=c enclose=none>#define</codesource>]]s, para que se nun futuro fose preciso ampliar estes valores, se poida facer con poucos cambios e sen ter que andar a buscar a función (ou funcións) no código.
 
De todos xeitos, salvo que vaiamos utilizar unha función só con matrices das que coñecemos a extensión de cada unha das súas dimensións, o mellor será que se traballe coa matriz de varias dimensións coma se en realidade fose unha matriz dunha soa dimensión, pois isto posibilitará que unha mesma función poida traballar con funcións con dimensións de extensión moi variable.
 
En caso de que vaiamos traballar únicamenteunicamente con unha parte da matriz, non vale simplemente traballar con ela coma se fose de menor tamaño do que en realidade é. Tense que traballar de xeito que o programa sexa consciente en todo momento
da verdadeira extensión das dimensións da matriz. E o que hai que facer é, a maiores, conseguir que a función ignore as celas que non interesen.
 
{{Navegador|PunteirosMoldes|Cadeas de caracteres}}
==Véxase tamén==
===Apéndice===
*[[{{BASEPAGENAME}}/Funcións matriciais|Funcións para traballar con matrices]].
 
 
{{Navegador|Punteiros|Cadeas de caracteres}}
 
<!-- Categorías: -->
[[Categoría:C ─ Tipos de datosVariables|Matrices]]