Saltar al contenido principal
LibreTexts Español

4.6: definir

  • Page ID
    82499
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Muy a menudo es deseable utilizar constantes simbólicas en lugar de valores reales. Por ejemplo, probablemente preferirías usar un símbolo como PI en lugar del número 3.14159. Esto se puede hacer con la directiva de preprocesador #define. Estos normalmente se encuentran en archivos de cabecera (como stdio.h o math.h) o en la parte superior de un módulo de código fuente C. Es posible que veas algo como:

    #define PI 3.14159

    Una vez que el compilador vea esto, cada vez que se encuentre con el PI de token lo reemplazará con el valor 3.14159. Esta directiva utiliza una simple sustitución pero se pueden hacer muchas cosas más complicadas que esto. Por ejemplo, también puedes crear algo que parezca una función:

    #define parallel((x),(y))     ((x)*(y))/((x)+(y))
    

    Los x e y sirven como marcadores de posición. Así, la línea

    a = parallel( b, c );

    se expande a:

    a = (a*b)/(a+b);
    

    ¿Por qué hacer esto? Porque es una expansión en línea o macro. Eso significa que no hay sobrecarga de llamadas de función y la operación se ejecuta más rápido. Al mismo tiempo, se lee como una función, por lo que es más fácil para un programador seguir. Bien, pero ¿por qué todos los paréntesis adicionales? La razón es porque x e y son marcadores de posición, y esos elementos pueden ser expresiones, no variables simples. Si lo hiciste de esta manera podrías meterte en problemas:

    #define parallel(x,y)   x*y/(x+y)
    

    ¿Y si x es una expresión, como en el siguiente ejemplo?

    a = parallel(2+b,c);

    Esto se ampliaría a:

    a = 2+b*c/(2+b+c);

    Como la multiplicación se ejecuta antes de la suma, se termina con 2 que se agrega al producto de b veces c después de la división, que no es lo mismo que la suma de 2 y b se multiplica por c, y esa cantidad entonces siendo divididos. Mediante el uso de los paréntesis adicionales, se mantiene el orden de ejecución.

    Refiriéndose de nuevo a las operaciones de campo de bits, aquí hay algunas definiciones útiles para lo que parecen ser funciones pero que son, de hecho, operaciones bit a bit expandidas en línea:

    #define bitRead(value, bit)    (((value) >> (bit)) & 0x01)
    #define bitSet(value, bit)     ((value) |= (1UL << (bit)))
    #define bitClear(value, bit)   ((value) &= ~(1UL << (bit)))

    El 1UL simplemente significa 1 expresado como un largo sin signo. Finalmente, bit también podría definirse como un símbolo que conduce a un código de autodocumentación de aspecto agradable:

    #define LEDBIT 7
    
    // more code here...
    
    bitSet( DDR, LEDBIT );

    Las expansiones #define pueden llegar a ser bastante complicadas porque pueden tener referencias anidadas. Esto significa que un #define puede contener dentro de él un símbolo que es en sí mismo un #define. Seguir estos puede ser un poco tedioso a veces pero en última instancia valen la pena el esfuerzo. Vamos a mirar a unos cuantos en el camino. Recuerda, estos se hacen para facilitar la programación del día a día, no para ofuscar el código. Por ahora, comience con simples sustituciones constantes matemáticas. Son extremadamente útiles y fáciles de usar. Solo ten en el fondo de tu mente que, con los microcontroladores, a los registros y puertos específicos a menudo se les dan nombres simbólicos como PORTB para que no tengas que recordar las direcciones numéricas precisas de ellos. La norma es colocar estas constantes simbólicas en TODAS LAS CAPS.


    This page titled 4.6: definir is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by James M. Fiore via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.