C/Directrices para o preprocesador: Diferenzas entre revisións

Contido eliminado Contido engadido
Gallaecio (conversa | contribucións)
Revisión completa. Agora toda completar.
Gallaecio (conversa | contribucións)
Completado!
Liña 5:
|} <!-- Isto sitúa o índice á dereita -->
 
O ''preprocesador'' de C identificaexecuta todasunha asserie liñasde instrucións antes de códigoque comece a verdadeira compilación do programa. Estas instrucións son as directrices para o ''preprocesador'', e son todas as liñas que comecencomezan polo caráctersímbolo <code>#</code>. comaEstas ordesinstrucións permiten establecer condicións para ela compilación ou non de fragmentos de código, incluír ficheiros con código adicional, etc. todo antes de que o código sexa compilado. As principais ordes para o ''preprocesador'' son [[#.23include|<source lang=c enclose=none>#include</source>]] e [[#.23define|<source lang=c enclose=none>#define</source>]].
 
Entre as vantaxes das directrices para o ''precompilador'' están a ''portabilidade'' do código fonte ou a mellora da comprensión do código.
 
==<source lang=c enclose=none>#define</source>==
:''Prefírese o uso de variables [[{{BASEPAGENAME}}/Modificadores#const|constantes]] no seu lugar sempre que sexa posible.''
Esta orde permite realizar substitucións sistemáticas de texto ao longo dun código fonte antes de que comece a compilación. O feito de que os cambios se introduzan antes da compilación dificulta a tarefa de buscar os erros causados por ocorrencias desta directriz. A súa sintaxe fundamental é a seguinte:
<source lang=c>
#define TEXTOCLAVE SUBSTITUCIÓNTEXTO
</source>
 
Onde:
*<code>TEXTOCLAVE</code> é oa textoclave a buscar (unha soa palabra) e
*<code>SUBSTITUCIÓNTEXTO</code> é oa textoexpresión que oa vai substituír.
 
Esta orde para o ''preprocesador'' permite, por exemplo, repetir un mesmo valor numérico como [[{{BASEPAGENAME}}/Constantes literais|constante]] varias veces ao longo dun mesmo código, e o máis importante, facilita a tarefa de cambiar dito valor en todo o código, reducíndoa a cambiar o valor no <source lang=c enclose=none>#define</source>. E en caso de utilizar palabras clave descritivas, permite asemade mellorar a comprensión do código fonte. É o caso do seguinte exemplo:
<source lang=c>
#define IVE 16L
Liña 28 ⟶ 30:
 
As palabras clave a utilizar cos <source lang=c enclose=none>#define</source> adoitan escribirse dun xeito que se evite calquera posible coincidencia accidental. Para iso adoitan escribirse completamente en maiúsculas, e comezar cunha barra baixa, «<code>_</code>».
 
<source lang=c enclose=none>#define</source> permite tamén definir unha clave a secas (sen asignarlle un texto de substitución), algo moi utilizado a día de hoxe para preparar o código fonte para as diferencias entre os distintos compiladores e as distintas plataformas, dado que mediante outras directrices ([[#.23ifdef|<source lang=c enclose=none>#ifdef</source>]] ou [[#.23ifndef|<source lang=c enclose=none>#ifndef</source>]]) pode utilizarse a definición ou non dunha clave como condición para outras directrices do ''preprocesador''.
 
<source lang=c enclose=none>#define</source> pode levar argumentos, o que permite definir dalgunha maneira funcións. Véxase o seguinte exemplo:
<source lang=c>
#define VALOR_ABSOLUTO( x ) ( ((x) < 0) ? -(x) : (x) )
// [...]
int x = -1;
if( ABSOLUTE_VALUE( x ) ) {
// [...]
</source>
 
===Convencións respecto das definicións de claves===
As seguintes convencións adoitan evitar erros frecuentes ao definir claves:
*Cómpre colocar as variables sempre entre parénteses no texto de substitución para asegurarse de que, se son expresións, se executen coa prioridade máis alta posible para non mesturarse con outros operadores.
*Se o texto de substitución é unha expresión, cómpre rodealo no seu conxunto de parénteses, polos mesmos motivos que no caso anterior.
*Se o texto de substitución contén máis dunha orde ou declaracións de variables, cómpre situalo dentro dun ciclo [[{{BASEPAGENAME}}/Instrucións de control#do while|<source lang=c enclose=none>do{ [...] } while(0)</source>]], sen rematalo en «<code>;</code>», de xeito que poda usarse no código coma unha simple orde.
*Cando sexa posible, evítese repetir un argumento no texto de substitución.
*Se unha substitución desaparecerá nun futuro para deixar paso a unha función, a clave debería nomearse igualq ue a futura función.
 
===<code>#</code>===
O operador «<code>#</code>» permite que o primeiro argumento que lle siga se converta nunha cadea de texto limitada con comiñas dobres, «<code>"</code>». Por exemplo, a seguinte instrución:
<source lang=c>
#define COMO_CADEA( t ) # t
</source>
Convertería o seguinte código:
<source lang=c>
puts( COMO_CADEA( MI MADRIÑA! ) );
</source>
Nestoutro:
<source lang=c>
puts( "MI MADRIÑA!" );
</source>
 
Aproveitando a propiedade de C que di que varias [[{{BASEPAGENAME}}/Cadeas de texto|cadeas de texto]] xuntas equivalen a unha única cadea, este operador permite inserir texto en cadeas de texto. Por exemplo, a seguinte instrución:
<source lang=c>
#define COMER( algo ) "Estou a comer " #t "."
</source>
Convertería o seguinte código:
<source lang=c>
puts( COMER( froita ) );
</source>
Nestoutro:
<source lang=c>
puts( "Estou a comer " "froita" "." ); // Interpretaríase coma unha única cadea.
</source>
 
===<code>##</code>===
O operador «<code>##</code>» concatena as variables dos seus dous extremos. Por exemplo, a seguinte instrución:
<source lang=c>
#define CONCATENAR( x, y ) x ## y
</source>
Convertería o seguinte código:
<source lang=c>
printf( "%d", CONCATENAR( x, y ));
</source>
Nestoutro:
<source lang=c>
printf( "%d", xy);
</source>
 
===Comezo habitual dos ficheiros de cabeceira===
Un uso habitual da directriz <source lang=c enclose=none>#define</source> é para a inclusión dos ficheiros de cabeceira nos códigos fonte, pois só se deben incluír unha vez. De maneira indirecta, é habitual incluír un ficheiro varias veces, dado que moitos ficheiros de cabeceira dependen á súa vez doutros. Mediante o uso de directrices condicionais xunto co <source lang=c enclose=none>#define</source>, pódese evitar a repetición. Para iso utilízase unha clave baseada xeralmente no propio nome do ficheiro de cabeceira. Véxase o seguinte exemplo:
<source lang=c>
#ifndef FICHEIRO_DE_CABECEIRA_H
#define FICHEIRO_DE_CABECEIRA_H
// Contido do ficheiro de cabeceira.
#endif
</source>
 
==<source lang=c enclose=none>#error</source>==
Esta instrución detén a compilación. A súa sintaxe básica é a seguinte:
<source lang=c>
#error MENSAXE
</source>
 
Adoita utilizarse para a depuración de código.
 
==<source lang=c enclose=none>#ifdef</source>==
Esta instrución analiza a expresión que lle segue, e segundo o seu valor sexa distinto de cero ou non, incluirá ou non un bloque de código. A súa sintaxe fundamental é a seguinte:
<source lang=c>
#if CONDICIÓN
// Bloque de código a incluír.
#endif
</source>
 
A <code>CONDICIÓN</code> pode conter calquera [[{{BASEPAGENAME}}/Operadores|operador]] salvo os de asignación, incremento, redución, enderezo e <source lang=c enclose=none>sizeof()</source>.
 
A directriz pode combinarse con outras dúas, <source lang=c enclose=none>#elif</source> e <source lang=c enclose=none>#else</source>. <source lang=c enclose=none>#elif</source> permite establecer máis bloques de código asignados a condicións dentro dun <source lang=c enclose=none>#if</source>. <source lang=c enclose=none>#else</source> permite establecer un bloque de código para cando non se cumpre a condición de ningún <source lang=c enclose=none>#if</source> ou <source lang=c enclose=none>#elif</source>. A seguinte é unha sintaxe máis completa do uso de <source lang=c enclose=none>#if</source>:
<source lang=c>
#if CONDICIÓN1
// Código 1.
#elif CONDICIÓN2
// Código 2.
#elif CONDICIÓN3
// Código 3.
// [...]
#elif CONDICIÓNn
// Código n.
#else
// Código se non se cumpre ningunha das condicións anteriores.
#endif // Fin do #if
</source>
 
==<source lang=c enclose=none>#ifdef</source>==
Liña 37 ⟶ 142:
</source>
 
OsEntre gruposas condicionais<source lang=c enclose=none>// Instrucións</source> pode haber outras directrices para o ''preprocesador'', mesmo poden aniñarse os grupos condicionais, pero de facerse ten que ser completamente. É dicir, o peche dun grupo condicional (<source lang=c enclose=none>#endif</source>) pecha o inicio de grupo condicional inmediatamente anterior (<source lang=c enclose=none>#ifdef</source>). Tampouco se pode distribuír un grupo condicional en ficheiros separados.
 
Aínda que non se definise previamente a <code>CLAVE</code> (e por tanto as instrucións non van estar presenten no código final), o ''preprocesador'' analizará sintacticamente as ordes do grupo condicional, polo que estas terán que seguir a sintaxe da linguaxe C de todos xeitos.
Liña 56 ⟶ 161:
 
==<source lang=c enclose=none>#pragma</source>==
===Incluír bibliotecas de Windows<ref>[http://techbrahmana.blogspot.com/2008/04/pragma-commentlib-cool-way-to-indicate.html Blogue “I Think Tech”] (''en inglés'').</ref>===
Mediante a seguinte liña, substituíndo <code>biblioteca</code> polo nome da biblioteca en cuestión, pódese especificar en [[Windows]] unha biblioteca da que depende o código fonte. O nome da biblioteca, tal e como se amosa a continuación, debe ir delimitado por comiñas dobres (<code>"</code>).
<source lang=c>
#pragma comment(lib, "biblioteca")
</source>
 
==<source lang=c enclose=none>#undef</source>==
Esta directriz cancela a definición dunha clave que se definiu previamente.
 
==Notas==
<references />
 
==Véxase tamén==
Liña 70 ⟶ 181:
<!-- Categorías: -->
[[Categoría:C ─ Elementos|Directrices para o preprocesador]]
 
<!-- Noutros wikibooks -->
[[en:C Programming/Preprocessor]]