014 Programacion en c++

download 014 Programacion en c++

of 55

Transcript of 014 Programacion en c++

  • 5/26/2018 014 Programacion en c++

    1/55

    8 Asignaciones compuestas con operadores de bits

    Salvo el complemento a uno (~) que es unitario, los dems operadores de menejo de bits pueden

    combinarse con la asignacin simple (=) para dar lugar a una asignacin compuesta( 4.9.2).

    Recuerde que:

    x &= y; // equivale a: x = (x & y);x ^= y; // equivale a: x = (x ^ y);x |= y; // equivale a: x = (x | y);x > y);

    Ejemplo

    #include

    int main() {signed int x = 2, y = 7, z = 6, a = 2, b= -2;x &= -2;y ^= -2;z |= 13;a = 1;cout

  • 5/26/2018 014 Programacion en c++

    2/55

    Comentario: en el cuadro se muestra un cuadro sinptico con los resultados de aplicar losoperadores AND, XOR y OR entre dos enteros caractersticos (los valores 0 y 1):

    E101

    01

    E200

    11

    E1&E200

    01

    E1^E201

    10

    E1 |E201

    11

    9 En ocasiones los operadores de bits se utilizan para compactar la informacin, logrando que untipo bsico (por ejemplo un long) almacene magnitudes ms pequeas mediante

    aprovechamientos parciales de los bits disponibles ( 2.2.4).

    Considere el significado de las siguientes macros ( 4.9.10b)utilizadas por el compilador MSVisual C++ que expresan valores de color en programas MS Windows:

    #define RGB(r,g,b)((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))24))

    Comentario

    Algunas de las etiquetas utilizadas (como COLORREF, DWORDo BYTE) son a su vez typedefs (

    3.2.1a), muy comunes en la programacin para los entornos Windows ( Ejemplo).

    Las expresiones del tipo (WORD)(w)son expresiones de modelado de tipos ( 4.9.9).

    Observe la codificacin RGBen la que el color est representado por sus tres componentes [2]Rojo (Red), verde (Green) y azul (Blue). Est claro que los valores de cada componente puedenocupar un mximo de 8 bits en la expresin resultante, de forma que pueden estar comprendidos

    entre 0 y 256 ( 0.1).

    En la codificacin CMYKel color est representado por cuatro componentes: Cian (Cyan),magenta (Magenta), amarillo (Yellow) y negro (black). Los valores de cada componente puedenestar igualmente comprendidos entre 0 y 256, aunque el valor "resultante" es sensiblemente mayor

    http://www.zator.com/Cpp/E2_2_4.htmhttp://www.zator.com/Cpp/E2_2_4.htmhttp://www.zator.com/Cpp/E2_2_4.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E3_2_1a.htmhttp://www.zator.com/Cpp/E3_2_1a.htmhttp://www.zator.com/Cpp/E3_2_1a.htmhttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E4_9_9.htm#Estilo%20cl%C3%A1sicohttp://www.zator.com/Cpp/E4_9_9.htm#Estilo%20cl%C3%A1sicohttp://www.zator.com/Cpp/E4_9_9.htm#Estilo%20cl%C3%A1sicohttp://www.zator.com/Cpp/E4_9_3.htm#[2]http://www.zator.com/Cpp/E4_9_3.htm#[2]http://www.zator.com/Cpp/E4_9_3.htm#[2]http://www.zator.com/Cpp/E0_1.htm#Sistema%20binariohttp://www.zator.com/Cpp/E0_1.htm#Sistema%20binariohttp://www.zator.com/Cpp/E0_1.htm#Sistema%20binariohttp://www.zator.com/Cpp/E0_1.htm#Sistema%20binariohttp://www.zator.com/Cpp/E4_9_3.htm#[2]http://www.zator.com/Cpp/E4_9_9.htm#Estilo%20cl%C3%A1sicohttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E3_2_1a.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E2_2_4.htm
  • 5/26/2018 014 Programacion en c++

    3/55

    que en la codificacin RGB. En ambos casos el resultado es modelado de forma que produzca

    un COLORREF, que en dicho compilador corresponde a ununsigned long, cuyo tamao es de 4

    bytes ( 4.9.13). Cuando una constante de este tipo est representada en hexadecimal, adopta lasiguiente forma:

    COLORREF ulColor = 0x00bbggrr;

    donde bb, ggy rrson respectivamente las componentes azul, verde y roja del color representado.

    Naturalmente estos valores estn en el rango 00 - FF.

    8.1 Ejemplo

    #include using namespace std;typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned long DWORD;typedef DWORD COLORREF;

    #define RGB(r,g,b)((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))16))

    int main() { // =================int r = 10, g = 20, b = 30;unsigned long rgbColor = RGB(r, g, b);cout

  • 5/26/2018 014 Programacion en c++

    4/55

    An suponiendo que el lector no vaya a dedicarse a esto de la programacin y lo haga soloespordicamente, es ms que probable que antes o despus tenga que habrselas con el manejode bits individuales. Eso sin contar con que su utilizacin es constante en determinados entornos.Por ejemplo, cuando se programan sistemas embebidos ("Embedded Systems"); interfacesanalgico-digitales; sistemas de comunicaciones; de adquisicin de datos, Etc. Incluimos aqualgunos consejos, trucos y tecnicismos que le ayudarn a familiarizarse con el manejo de bits, algopor lo dems bastante sencillo cuando se dominan un par de trucos bsicos.

    Nota: en el lenguaje informtico es frecuente utilizar la palabra "setear" (del ingls "set") paraindicar que uno, o todos los bits de una palabra, se ponen a uno, y limpiar ("Clear") parasealar que se ponen a cero. Aunque no est recogido en el diccionario de la AcademiaEspaola de la Lengua, utilizamos este anglicismo (setear) por ser ms breve que "poner auno".

    2 Construir un patrn de bits

    Es muy frecuente que las manipulaciones de bits requieran la construccin de un patrndeterminado ("bitmask"), que sirva como plantilla para comparaciones u operando de una

    expresin. Por supuesto, la forma ms directa es escoger un nmero de longitud adecuada y echarmano de nuestros conocimientos de lgebra binaria para calcular el valor correspondiente delpatrn deseado. Por ejemplo, necesitamos una plantilla de 16 bits con el siguiente aspecto:

    11011000 00010000

    Podemos "sacar la cuenta" y llegar a la conclusin de que nuestra declaracin para el nmerodebe ser:

    unsigne int X = 55312;

    Cuando el patrn es ms largo, 32 o 64 bits, el clculo puede ser muy tedioso. Por ejemplo:

    11111010 01011000 11011100 01100110

    En estos casos no es necesario pasar el resto de la tarde para encontrar que correspondeexactamente con el unsigned long4200127590. Una alternativa es calcular el valor individual decada octeto y componer el resultado utilizando el operador OR inclusivo y los desplazamientosadecuados. En nuestro caso, el valor de los octetos (de izquierda a derecha) es: 250, 88, 220 y102. El nmero Xcorrespondiente a esa plantilla de bits es el siguiente:

    unsigned long X = (250UL

  • 5/26/2018 014 Programacion en c++

    5/55

    (unsigned char) 0x3 00000011

    (unsigned char) 0x4 00000100

    (unsigned char) 0x7 00000111

    (unsigned char) 0x8 00001000

    (unsigned char) 0xF 00001111

    (unsigned char) 0x10 00010000

    (unsigned char) 0x20 00100000

    (unsigned char) 0x40 01000000

    (unsigned char) 0x80 10000000

    (unsigned short) 0xF 00000000 00001111

    (unsigned int) 0xF00000000 00000000 00000000

    00001111

    (unsigned char) 0xFF 11111111

    (unsigned short) 0xFF 00000000 11111111

    (unsigned int) 0xFF00000000 00000000 00000000

    11111111

    (unsigned short) (0xFF

  • 5/26/2018 014 Programacion en c++

    6/55

    (unsigned short) 0xFFF 00001111 11111111

    (unsigned short) 0xFFFF 11111111 11111111

    (unsigned int) 0xFFF

    00000000 00000000 00001111

    11111111

    (unsigned int) 0xFFFF00000000 00000000 11111111

    11111111

    (unsigned int) (0xFF | 0xFF

  • 5/26/2018 014 Programacion en c++

    7/55

    Y = X ^ M;

    En nuestro caso:

    unsigned int Y = X ^ (0xFF | 0xFF

  • 5/26/2018 014 Programacion en c++

    8/55

    El problema es inverso al anterior: queremos que la resultante Rsea igual a la mscara M, con lasalvedad de que los bits que estuvieran seteados en P, sean limpiados (puestos a 0) en R.

    R = M & (~P);

    Si lo que queremos es modificar Men el sentido indicado, la expresin es:

    M &= ~P;

    7 Comprobar si un patrn encaja en una mscara

    El problema consiste en verificar si los bits seteados (que estn a 1) en un patrn Ptienencorrespondencia con los bits correspondientes de una patrn M(tambin estn a 1 en M). Laverificacin cierto/falso, viene determinado por la expresin (M & P). Por ejemplo:

    if ( M & P) ... // Encajaelse ... // No encaja

    En las aplicaciones reales, es frecuente que los patrones y las mscaras estn identificadosmediante constantes cuyos valores se incluyen en "defines". Por ejemplo, en la programacinWindows, el estilo de una ventana est definido por un valor entero en el que cada uno de sus bitstiene un significado y efecto concreto. El programador puede componer un estilo particularcombinando los componentes individuales que estn definidos mediante constantes. Por ejemplo:

    DWORD style = WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE |ES_WANTRETURN |

    ES_AUTOVSCROLL | ES_NOHIDESEL,

    Como indicbamos en la pgina anterior, DWORDes un typedefcuya traduccin exacta depende de

    la plataforma, pero que probablemente ser traducida a un unsigned long. A su vez, las

    constantes a la derecha (WS_CHILD | WS_VISIBLE | WS_VSCROLL, etc.) que determinan los

    distintos componentes del estilo, estn definidas en los ficheros de cabecera de forma que sonDWORDs cuyos valores tienen un bit a uno y los dems a cero, por lo que son mltiplos de 2(dentro de la serie 1, 2, 4, 8, 16, 32, 64, etc). Al programador no le interesan sus valoresconcretos, solo sus nombres, que por lo dems son bastante descriptivos. Algunas caractersticasdel estilo pueden ser modificadas en runtime despus de creada la ventana, de forma que sonnormales trozos de cdigo como el que sigue:

    DWORD style = GetWindowLong(hwnd, GWL_STYLE); // se obtiene el estilo deuna ventana

    switch(mode) { // mode depende de una orden de usuario/* ... */case EDIT_UPPER: // orden de texto solo en maysculas

    style &= ~ ES_LOWERCASE;style |= ES_UPPERCASE;break;

    case EDIT_LOWER: // orden de texto solo en minsculasstyle &= ~ ES_UPPERCASE;style |= ES_LOWERCASE;break;

  • 5/26/2018 014 Programacion en c++

    9/55

    case EDIT_NONE: // orden contenido de ventana no editablestyle &= ~(ES_UPPERCASE | ES_LOWERCASE);break;

    }SetWindowLong(hwnd, GWL_STYLE, style); // establecer nuevo estilo deventana

    8 Simplificacin de expresiones lgicas

    Es frecuente que en la programacin de interfaces analgico/digitales; tarjetas de adquisicin dedatos; dispositivos embebidos; sistemas de comunicacin y dems parafernalia electrnica del tipocitado en la introduccin de este captulo, se utilicen expresiones lgicas que pueden resultar

    bastante complicadas. De forma similar a cmo en una expresin del tipo a = b + 2c + 1.5b

    -4c -3podemos simplificar y poner finalmente que a = 2.5b -2c -3, el lgebra lgica permite

    utilizar ciertas identidades que pueden ayudarnos a la simplificacin de las expresiones

    resultantes. En la tabla adjunta se muestran algunas de estas reglas [1].

    !(!x) == xx | x == xx | !x == true!x | !y == !(x & y) //Teorema de DeMorgan!x & !y == !(x | y) //Teorema de DeMorganx & x == xx & !x == falsex | y == y | x //propiedad conmutativax & y == y & x //propiedad Conmutativa(x | y) | z == x | (y | x) //propiedad Asociativa(x & y) & z == x & (y & z) //propiedad Asociativax & y | x & z == x & (y | z) //propiedad Distributiva(x | y) & (x | x) == x | (y & z) //propiedad Distributiva

    x | x & y == xx & y | x & !y == x(x & y) | (!x & z) | (y & z) == (x & y) | (!x & z)(x | y) & (!x | z) & (y | z) == (x | y) & (!x | z)x & (x | y) == x(x | y) & (x | !y) == x

    4.9.5 Operador Coma

    1 Sinopsis

    En C++ la coma puede ser un elemento de puntuacin (separador de expresiones 3.2.6)y

    unoperador, dando lugar a las denominadasexpresiones con coma( 4.10.5).

    2 Sintaxis

    expresion , expresion-de-asignacion

    http://www.zator.com/Cpp/E4_9_3a.htm#[1]http://www.zator.com/Cpp/E4_9_3a.htm#[1]http://www.zator.com/Cpp/E4_9_3a.htm#[1]http://www.zator.com/Cpp/E3_2_6.htm#Comahttp://www.zator.com/Cpp/E3_2_6.htm#Comahttp://www.zator.com/Cpp/E4_10_5.htmhttp://www.zator.com/Cpp/E4_10_5.htmhttp://www.zator.com/Cpp/E4_10_5.htmhttp://www.zator.com/Cpp/E4_10_5.htmhttp://www.zator.com/Cpp/E3_2_6.htm#Comahttp://www.zator.com/Cpp/E4_9_3a.htm#[1]
  • 5/26/2018 014 Programacion en c++

    10/55

    3 Comentario

    La coma separa elementos en las listas de parmetros de las funciones, tambin se usa como unoperador en las expresiones con coma. Es legal mezclar ambos usos, pero deben usarseparntesis para distinguirlas y evitar ambigedades. Por ejemplo, la expresin:

    func(i, (j = 1, j + 4), k);

    llama afunccon tres argumentos: (i, 5, k), no cuatro.

    Cuando la coma se usa como operador, por ejemplo: E1, E2, el operando de la izquierdaE1esevaluado como una expresinvoid(no produce ningn resultado), despus se evala la

    expresinE2de la derecha, su valor y tipo son los que toma la expresin de coma. Por recursin,

    la expresin:E1, E2, ..., En, produce la evaluacin de izquierda a derecha de todas las

    expresionesEiy la expresin total adopta el valor deEn.

    Es el operador de precedencia ( 4.9.0a)ms baja de todos.

    4 Ejemplos

    sum = (i = 3, i++, i++); // sum = 4, i = 5func((exp1, exp2), (exp3, exp4, exp5)); // llama a func con dosargumentosreturn pass ? (puts("Acierto!"), 0) : (puts("Fallo!"), 1);

    La invocacin afuncen la segunda lnea se realiza con dos argumentos, los resultadosdeexp2yexp5respectivamente.

    En la tercera lnea, el programa devuelve 0 o 1 segn el valorpass, pero previamente indica elresultado en pantalla, ya que las dos alternativas conducen a la ejecucin de una expresin concoma.

    El operador coma debe ser usado con moderacin y es frecuentemente utilizado en los

    buclesforcomo en el ejemplo.

    void reverse (char s[]) { // invertir la cadenasint c, i, j;for ( i = 0 , j = strlen(s)-1 ; i < j ; i++, j--) {

    c = s[i], s[i] = s[j], s[j] = c;}

    }

    Como ejercicio, intente el lector desentraar la lgica de funcionamiento de la funcinreverse,que recibe una matriz de caracteres y la invierte. Como ayuda, tenga en cuenta que el

    argumentodel bucle for ( 4.10.3), es una expresin con coma. Comocomplemento, intente figurarse como se utiliza la cadena resultante si la funcin se define como

    devolviendovoid.

    http://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_10_3.htm#forhttp://www.zator.com/Cpp/E4_10_3.htm#forhttp://www.zator.com/Cpp/E4_10_3.htm#forhttp://www.zator.com/Cpp/E4_10_3.htm#forhttp://www.zator.com/Cpp/E4_9_0a.htm
  • 5/26/2018 014 Programacion en c++

    11/55

    Observe que esta posibilidad, incluir expresiones con coma en el argumento delos bucles, permite combinaciones muy interesantes y una notacin muy compacta, aunqueresultan algo crpticas en una primera lectura.

    4.9.6 Operado r Cond icio nal

    1 Sinopsis

    El operador condicional es el nico operador ternario de la gramtica C++ y sirve para tomardecisiones. Proporciona un resultado entre dos posibilidades en funcin de una condicin.

    Nota: Puede afirmarse que este operador ha hecho fortuna, ya que existe con la mismasintaxis e idntico comportamiento, en multitud de otros lenguajes de programacin.

    2 Sintaxis

    expresion-relacional ?expr1 : expr2

    3 Comentario

    El operador condicional ? :produce un resultado. En la expresin E1 ? E2 : E3, E1es una

    expresin relacional ( 4.9.12)que se evala primero. Si el resultado es cierto, entonces se

    evala E2y este es el resultado. En caso contrario (si E1resulta falso), entonces se evala E3y

    este es el resultado. Observe que si la premisa E1es cierta, entonces no llega a evaluarse la

    expresin E3.

    3.1 El operador ? :puede usarse para sustituir ciertas sentencias del tipo if-then-else, aunque

    puede conducir a expresiones ms compactas que las correspondientes if...else. En el ejemploque sigue, a yse le asigna el valor 100:

    x = 10;y = x > 9 ? 100 : 200;

    3.2 No es necesario poner parntesis en la primera expresin (E1), ya que la precedencia (

    4.9.0a)de ? :es muy baja (justamente sobre la asignacin = ). De todos modos, es aconsejableponerlos por legibilidad.

    y = (x > 9)? 100 : 200;

    3.3 En caso de que E1no sea una expresin relacional, debe ser un escalar reducible a

    un booleano(Conversin de tipos 3.2.1b). Por ejemplo es vlido:

    int y = 6 ? 7: 8;

    aunque en este caso el resultado sera siempre y == 7(el int6 se se traduce en el

    booleano true).

    http://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E3_2_1b.htm#Conversi%C3%B3n%20de%20tiposhttp://www.zator.com/Cpp/E3_2_1b.htm#Conversi%C3%B3n%20de%20tiposhttp://www.zator.com/Cpp/E3_2_1b.htm#Conversi%C3%B3n%20de%20tiposhttp://www.zator.com/Cpp/E4_9_0a.htmhttp://www.zator.com/Cpp/E4_9_12.htm
  • 5/26/2018 014 Programacion en c++

    12/55

    3.4 En ocasiones se aprovechan los efectos laterales ( 4.9)del operador para producir unresultado. Ejemplo:

    ++x ? ++y : --z;

    El compilador GNU cpp permite la ausencia del segundo operando en este tipo de expresiones.Por ejemplo, es vlido:

    x ? : z; // E1

    El resultado de esta expresin es el valor de xsi este es distinto de cero, y zen caso contrario. Porconsiguiente, es equivalente a:

    x ? x : z; // E2

    El manual informa que este tipo de expresiones solo son de utilidad en caso de que la evaluacin

    de xtenga efectos laterales (por ejemplo, que sea utilizada como argumento en una funcin), encuyo caso la expresin E2 tendra efecto lateral doble sixes distinto de cero. La omisin delsegundo operador en E1 evitara esta computacin indeseada y dejara el valor previamentecomputado sin que se produzca un doble efecto.

    4 E2 y E3 deben seguir las reglassiguientes:

    1. Si E2 y E3 son de tipos distintos, se realiza una conversin de tipo estndar, de forma queel resultado ser siempre del mismo tipo, con independencia de E1.

    2. Si E2 y E3 son de tipos unin o estructuras compatibles. El resultado es una unin oestructura del tipo de E2 y E3.

    3. Si E2 y E3 son de tipo void, el resultado es void.

    4. Ambos operandos son punteros a versiones cualificadas o no cualificadas de tiposcompatibles. El resultado es un puntero a cualquiera de los tipos de ambos operandos.

    5. Un operando es un puntero y el otro es un puntero nulo. El resultado es un puntero quepuede sealar a un tipo del primero o del segundo operando.

    6. Un operando es un puntero a un objeto o tipo incompleto, y el otro es un puntero a unaversin cualificada o no cualificada de void. El tipo resultante es el del puntero distinto devoid.

    5 Ejemplos

    5.1 Suponiendo que ze ysean Lvalues, las siguientes expresiones son equivalentes:

    (x ? y : z) = 10;(x ? y = 10 : (z = 10));

    5.2 El bucle que sigue imprime nelementos de una matriz, 10 por lnea, con cada columna

    separada por un espacio y con cada lnea terminada por un NL (nueva lnea), incluida la ltima.

    for (i = 0; i < n; i++)printf ("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');

    http://www.zator.com/Cpp/E4_9.htmhttp://www.zator.com/Cpp/E4_9.htmhttp://www.zator.com/Cpp/E4_9.htmhttp://www.zator.com/Cpp/E4_9.htm
  • 5/26/2018 014 Programacion en c++

    13/55

    5.3 Ejemplo:

    printf ( "Tienes %d item%s.\n", n, n==1 ? "" : "s");

    5.4 Ejemplo:

    #include #include

    int main(void) { // ============time_t t;time(&t);struct tm* petm = localtime(&t);long dgt = _timezone/60;cout

  • 5/26/2018 014 Programacion en c++

    14/55

    2 && Operador Y lgico

    Tambin denominado por su nombre en ingls (generalmente en maysculas) AND lgico.

    Devuelve un valor lgicotruesi ambos operandos son ciertos. En caso contrario el resultadoesfalse.

    Sintaxis

    expr-AND-logica&&expresion-OR-inclusive

    Comentario:

    La operatoria es como sigue: El primer operando (de la izquierda) es convertido a bool. Para ello,si es una expresin, se evala para obtener el resultado (esta computacin puede tener ciertos

    efectos laterales). A continuacin, el valor obtenido es convertido aboolcierto/falso siguiendo las

    reglas de conversin estndar ( 3.2.1b). Si el resultado esfalse, el proceso se detiene y este esel resultado, sin que en este caso sea necesario evaluar la expresin de la derecha (recurdeseque en el diseo de C++ prima la velocidad).

    Si el resultado del operando izquierdo es cierto, se contina con la evaluacin de la expresin de la

    derecha, que tambin es convertida abool. Si el nuevo resultado estrue, entonces el resultadodel operador estrue. En caso contrario el resultado esfalse.

    Nota: la Norma informa que antes de ser evaluada la expresin derecha, han sucedido todoslos posibles efectos laterales de la expresin izquierda, a excepcin de la destruccin de losposibles objetos temporales que se hubiesen creado.

    Ejemplo:

    int m[3] = {0,1,2};int x = 0;if (m && x) cout

  • 5/26/2018 014 Programacion en c++

    15/55

    else cout

  • 5/26/2018 014 Programacion en c++

    16/55

    else cout

  • 5/26/2018 014 Programacion en c++

    17/55

    SiEes una expresin,!Ees equivalente a (0==E). Como consecuencia, las expresiones quesiguen son equivalentes dos a dos:

    if (! valid);if (valid == 0);

    ...if (valid);if (valid != 0);

    7 Representacin explcita

    Los operadores lgicos entre valores lgicos&&,||,!; la relacin de desigualdad!=; algunos de losoperadores lgicos entre bits (&,|,^,~) y sus expresiones compuestas (&=,|=,^=), tienen unarepresentacin realmente difcil de leer, con la desventaja adicional que sus smbolos no siempreestn fcilmente accesibles en ordenadores con teclados distintos del estndar USA. Para resolvereste problema, el Estndar C++ ha introducido nuevas formas para su representacin; lasdenominamos formas explcitas o naturales, en razn de que se parecen ms a las palabrascorrespondientes del lenguaje natural. Las nuevas formas constituyen palabras-clave, y la tabla deequivalencias es la siguiente:

    Palabra claveSmboloReferencia Descripcin

    and && Operador Y lgicoor || Operador O lgiconot ! Operador negacin lgicabitand & 4.9.3 Operador AND entre bitsxor

    ^ 4.9.3 Operador OR exclusivo entrebitsbitor

    | 4.9.3 Operador OR inclusivo entrebitscompl

    ~ 4.9.3 Operador complemento auno de bitsand_eq

    &= 4.9.3 Asignacin compuesta (ANDentre bits)xor_eq

    ^= 4.9.3 Asignacin compuesta (XORentre bits)

    http://www.zator.com/Cpp/E4_9_3.htm#ANDhttp://www.zator.com/Cpp/E4_9_3.htm#ANDhttp://www.zator.com/Cpp/E4_9_3.htm#XORhttp://www.zator.com/Cpp/E4_9_3.htm#XORhttp://www.zator.com/Cpp/E4_9_3.htm#ORhttp://www.zator.com/Cpp/E4_9_3.htm#ORhttp://www.zator.com/Cpp/E4_9_3.htm#Complementohttp://www.zator.com/Cpp/E4_9_3.htm#Complementohttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_8.htmhttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Complementohttp://www.zator.com/Cpp/E4_9_3.htm#ORhttp://www.zator.com/Cpp/E4_9_3.htm#XORhttp://www.zator.com/Cpp/E4_9_3.htm#AND
  • 5/26/2018 014 Programacion en c++

    18/55

    or_eq|= 4.9.3 Asignacin compuesta (ORentre bits)

    not_eq!= 4.9.12 Operador relacional dedesigualdad

    Nota: ni el compilador Borland C++ 5.5 ni MS VC++ 6.0 soportan esta caracterstica del estndar,aunque el de Microsoft anuncia en su documentacin que pueden utilizarse "defines" (

    4.9.10b). Por ejemplo:

    #define bitand define bitor |#define and_eq &=#define or_eq |=#define not_eq !=

    Por su parte, el compilador GNU gcc dispone de la opcin de compilacin -fno-operator-names,que permite que las palabras-claveand,bitand,bitor,compl,not, yor,nosean tratadas comosinnimos de los operadores correspondientes.

    Temas relacionados:

    Trigrafos y digrafos ( 3.2.3e)

    Sobrecarga de los operadores lgicos ( 4.9.18g).

    4.9.9 Modelado de tipo s

    1 Sinopsis:

    Elmodelado de tipos("typecasting") es el proceso de convertir o promover un objeto de un tipo aotro. Esta operacin es necesaria y frecuente en programacin; incluso es realizada infinidad deveces por el compilador de forma automtica y transparente para el programador, y ocurre cuando

    este la solicita deforma implcita. Por ejemplo, cuando una funcin en cuyo prototipo se hadeclarado que espera unfloatcomo argumento y le pasamos un entero, o cuando necesitamossumar unintcon undouble. En todos estos casos, el compilador realiza automticamente una

    conversin de tipo para que el argumento pasado concuerde con el esperado ( 4.4.6). En el

    caso de operaciones aritmticas, la conversin intenta conseguir la menor prdida de precisinposible en las operaciones ( 2.2.5).

    En otros casos, que tratamos en este captulo, la necesidad de modelado es indicada en el cdigo

    deforma explcita, utilizando los recursos que proporciona el lenguaje con este propsito.

    2 Precauciones:

    http://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuestahttp://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E3_2_3e.htm#Trigrafoshttp://www.zator.com/Cpp/E3_2_3e.htm#Trigrafoshttp://www.zator.com/Cpp/E3_2_3e.htm#Trigrafoshttp://www.zator.com/Cpp/E4_9_18g.htmhttp://www.zator.com/Cpp/E4_9_18g.htmhttp://www.zator.com/Cpp/E4_9_18g.htmhttp://www.zator.com/Cpp/E4_4_6.htmhttp://www.zator.com/Cpp/E4_4_6.htmhttp://www.zator.com/Cpp/E4_4_6.htmhttp://www.zator.com/Cpp/E2_2_5.htm#Conversiones%20aritm%C3%A9ticas%20est%C3%A1ndarhttp://www.zator.com/Cpp/E2_2_5.htm#Conversiones%20aritm%C3%A9ticas%20est%C3%A1ndarhttp://www.zator.com/Cpp/E2_2_5.htm#Conversiones%20aritm%C3%A9ticas%20est%C3%A1ndarhttp://www.zator.com/Cpp/E2_2_5.htm#Conversiones%20aritm%C3%A9ticas%20est%C3%A1ndarhttp://www.zator.com/Cpp/E4_4_6.htmhttp://www.zator.com/Cpp/E4_9_18g.htmhttp://www.zator.com/Cpp/E3_2_3e.htm#Trigrafoshttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_12.htmhttp://www.zator.com/Cpp/E4_9_3.htm#Asignacion-compuesta
  • 5/26/2018 014 Programacion en c++

    19/55

    No olvidar que, cuando forzamos una conversin de tipo explcita o implcita, estamosquebrantando deliberadamente uno de los sistemas de seguridad de C++, basado precisamente enla comprobacin de tipos. El modelado puede ser causa de problemas, en especial (aunque noexclusivamente) cuando se trata de punteros. Por tanto, se recomienda usarlo con moderacin ysolo para resolver necesidades puntuales.

    No obstante lo anterior, es evidente que determinadas conversiones, como las que realiza elcompilador automticamente con tipos numricos, no presentan a veces ningn problema; todo loms prdidas de precisin. Sobre todo cuando la conversin se realiza en el sentido de nmerocon ms precisin a los de menos. Por ejemplo, el compilador puede realizar automticamente unaconversin de tipo para realizar las asignaciones:

    short s = 33;long n = s;float f = s;

    sin que exista prdida de precisin, puesto quelongyfloatpueden albergar a todos losshort(

    2.2.4). Este tipo de promocin se denominaconversin ensanchante. Sin embargo, lasconversiones en el sentido del tipo de ms precisin al de menos (conversin estrechante),

    puede resultar en una prdida de informacin o incluso en errores peligrosos. Considere la salidadel ejemplo siguiente:

    #include

    int main() {unsigned long ul = 5000;long l = ul; int y = ul; short s = ul;cout

  • 5/26/2018 014 Programacion en c++

    20/55

    un puente; en un monitor de electromedicina; el mezclador en una fbrica de alimentos, osimplemente durante la confeccin de nminas en el programa de administracin de una empresa[2].

    Otro ejemplo de conversin estrechante que conduce a un resultado aparentemente contradictorio

    en 2.2.4a.

    Tampoco existe ninguna advertencia respecto de la salida obtenida en el ejemplo de promocin de

    un entero a variable de enumeracin ( 4.9.9b), que fuerza al compilador a proporcionar unresultado evidentemente errneo.

    En general son potencialmente peligrosas las conversiones de tipo cuando ambos no utilizan el

    mismo tipo de alineacin interna ( 4.5.9a). Tambin cuando se trata de punteros ( 4.9.9d)

    3 Dos tipos

    Como se ha indicado, en C++ existen dos tipos de modelado:implcitoyexplcito. El primero esrealizado automticamente por el compilador cuando se mezclan tipos. Por ejemplo, las mentadasconversiones numricas, que permiten operaciones aritmticas entre tipos distintos. El segundo serealiza cuando el programador utiliza explcitamente el operador de modelado.

    Aunque no sea estrictamente necesario, se recomienda como regla de buena prctica, utilizardeclaraciones explcitas incluso en los casos de modelado implcito [1]. Sobre todo cuando sequiera poner nfasis en la conversin realizada. Por ejemplo:

    int x = 10;float fl = 10.0;int y = x + fl; // Ok. modelado implcitoint z = x + static_cast(fl); // Mejor !!

    Aparte de que el cdigo resultante es mucho ms explcito, esta prctica facilita la depuracin deposibles errores derivados de la mixtura de tipos.

    4 Dos estilos

    En el C++ Estndar coexisten dos formas de sintaxis para modelado: la nueva y la clsica(heredada de C), aunque esta ltima se desaconseja y est considerada como prctica a extinguir("Deprecated").

    Nota: el compilador GNU gcc dispone de la opcin-Wold-style-cast, que muestra un mensajede aviso si se utiliza el viejo estilo.

    4.1 Estilo C++ de modelado

    La nueva sintaxis utiliza cuatro palabras clave especficas

    (static_cast, reinterpret_cast, dynamic_castyconst_cast) y una sintaxis que se presta menosa confusin que la clsica (ver a continuacin). Aparte de la anterior, las razones argumentadas enfavor del nuevo estilo es que es menos propenso a obtener resultados indeseados y ms fcil delocalizar su ocurrencia en el cdigo.

    http://www.zator.com/Cpp/E4_9_9.htm#[2]http://www.zator.com/Cpp/E4_9_9.htm#[2]http://www.zator.com/Cpp/E4_9_9.htm#[2]http://www.zator.com/Cpp/E2_2_4a.htm#Ref-2http://www.zator.com/Cpp/E2_2_4a.htm#Ref-2http://www.zator.com/Cpp/E4_9_9b.htm#Peligro-1http://www.zator.com/Cpp/E4_9_9b.htm#Peligro-1http://www.zator.com/Cpp/E4_9_9b.htm#Peligro-1http://www.zator.com/Cpp/E4_6_1.htmhttp://www.zator.com/Cpp/E4_6_1.htmhttp://www.zator.com/Cpp/E4_6_1.htmhttp://www.zator.com/Cpp/E4_9_9d.htm#Ejemplo-1http://www.zator.com/Cpp/E4_9_9d.htm#Ejemplo-1http://www.zator.com/Cpp/E4_9_9d.htm#Ejemplo-1http://www.zator.com/Cpp/E4_9_9.htm#[1]http://www.zator.com/Cpp/E4_9_9.htm#[1]http://www.zator.com/Cpp/E4_9_9.htm#[1]http://www.zator.com/Cpp/E4_9_9.htm#[1]http://www.zator.com/Cpp/E4_9_9d.htm#Ejemplo-1http://www.zator.com/Cpp/E4_6_1.htmhttp://www.zator.com/Cpp/E4_9_9b.htm#Peligro-1http://www.zator.com/Cpp/E2_2_4a.htm#Ref-2http://www.zator.com/Cpp/E4_9_9.htm#[2]
  • 5/26/2018 014 Programacion en c++

    21/55

    4.1 Estilo clsico de modelado

    Es el estilo heredado de C que se mantiene por compatibildad, tiene dos variedades de notacin,aunque el nuevo Estndar C++ lo desaconseja en favor del nuevo estilo.

    Sintaxis:

    ()()

    Comentario

    El valor dese convierte al tipo definido porsiguiendo lasreglas estndar de conversin. Por ejemplo, la funcin de la Librera Estndarsqrt() esperaundoublecomo argumento, si queremos utilizarla con unintn, se puede utilizar cualquiera de lasexpresiones siguientes:

    sqrt((double) n); // primera forma de la sintaxissqrt(double (n)); // segunda forma de la sintaxis

    Observe quenno se altera, ya que la conversin se realiza antes de pasar el argumento a lafuncin. Observe tambin que si los parmetros se han especificado en el prototipo de la funcin,esta conversin de argumento no sera necesaria, ya que el compilador realiza automticamente elmodelado correspondiente.

    Las expresiones que siguen son vlidas en C++:

    double peso = 25;int * ptr;

    ptr = (int *)&peso;cout

  • 5/26/2018 014 Programacion en c++

    22/55

    A::A(B b) { /* asignacin */ }

    Ver comentarios y aclaraciones al respecto en: Constructores de conversin ( 4.11.2d1)

    Tema relacionado

    Sobrecarga del operador de modelado ( 4.9.18k)

    4.9.9a El operad or co nst _cast

    1 Sinopsis:

    La palabra claveconst_castidentifica un operador de uso muy especfico: sirve para poner oquitar los atributosconstovolatilede un objeto. La sintaxis general es:

    const_cast< T > (arg)

    En la expresin anterior,Tyargdeben ser del mismo tipo, excepto en los atributosconst(

    3.2.1c) yvolatile( 4.1.9).Tes el tipo al que se quiere convertir,arges el tipo de partida(ver ejemplo). El modelado es resuelto en tiempo de compilacin, y el resultado es del tipo T. Unasola expresinconst_castpuede poner o quitar el atributoconstovolatilea cualquier nmerode objetos.

    Ejemplo

    const int x = 10;int* iptr = &x; // Error!!

    Un intento de compilar las sentencias anteriores conduce a un error del compilador:

    invalid conversion from `const int*' to `int*'

    La razn es que se est intentando asignar la direccin de un int-consta un puntero-a-int, cuandose necesitara un puntero-a-int-const. Suponiendo que no queramos (o podamos) cambiar la

    definicin deiptr, el problema de la asignacin en la segunda lnea puede resolverse medianteun "casting" adecuado:

    const int x = 23;int* iptr = const_cast (&x); // Ok!!

    2 cons_cast con punteros

    El cambio de atributo puede utilizarse con punteros, de forma que un puntero a-tipoX-

    constantepuede ser convertido en puntero a-tipoXy viceversa. El cambio tambin puederealizarse con un puntero a-tipoX-volatile.

    http://www.zator.com/Cpp/E4_11_2d1.htm#Constructores%20de%20conversi%C3%B3nhttp://www.zator.com/Cpp/E4_11_2d1.htm#Constructores%20de%20conversi%C3%B3nhttp://www.zator.com/Cpp/E4_11_2d1.htm#Constructores%20de%20conversi%C3%B3nhttp://www.zator.com/Cpp/E4_9_18k.htmhttp://www.zator.com/Cpp/E4_9_18k.htmhttp://www.zator.com/Cpp/E4_9_18k.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E4_9_18k.htmhttp://www.zator.com/Cpp/E4_11_2d1.htm#Constructores%20de%20conversi%C3%B3n
  • 5/26/2018 014 Programacion en c++

    23/55

  • 5/26/2018 014 Programacion en c++

    24/55

    En la expresin anterior,Tyargdeben ser del mismo tipo, excepto en los atributos const(

    3.2.1c) yvolatile( 4.1.9).Tes el tipo al que se quiere convertir,arges el tipo de partida

    (ver ejemplo). El modelado es resuelto en tiempo de compilacin, y el resultado es del tipo T. Unasola expresinconst_castpuede poner o quitar el atributoconstovolatilea cualquier nmerode objetos.

    Ejemplo

    const int x = 10;int* iptr = &x; // Error!!

    Un intento de compilar las sentencias anteriores conduce a un error del compilador:

    invalid conversion from `const int*' to `int*'

    La razn es que se est intentando asignar la direccin de un int-consta un puntero-a-int, cuandose necesitara un puntero-a-int-const. Suponiendo que no queramos (o podamos) cambiar la

    definicin deiptr, el problema de la asignacin en la segunda lnea puede resolverse medianteun "casting" adecuado:

    const int x = 23;int* iptr = const_cast (&x); // Ok!!

    2 cons_cast con punteros

    El cambio de atributo puede utilizarse con punteros, de forma que un puntero a-tipoX-

    constantepuede ser convertido en puntero a-tipoXy viceversa. El cambio tambin puederealizarse con un puntero a-tipoX-volatile.

    El puntero obtenido es idntico al original en todos los dems aspectos. Si la conversin tiene xitoel puntero resultante seala al mismo objeto que el original. Ejemplo:

    const int kte = 35;int* ptr;ptr = &kte; // Error!ptr = (int*) &kte; // modelado antiguo desaconsejadoptr = const_cast (&kte); // Ok:volatile int x = 45;ptr = &x; // Error!ptr = const_cast (&x); // Ok:

    As pues, este operador convierte un objeto (o referencia a objeto)constovolatileen un objeto (oreferencia) no-consto no-volatileque es idntico en lo dems al original.

    Es importante advertir que el operadorconst_castno cambia el tipodel operando, lo quesignifica que este operador no hace que una variable constante pueda volverse no-constante y veralterado su valor despus de aplicado el operador. Considere detenidamente el resultado obtenidoen el siguiente ejemplo, e intente llegar a una explicacin (recuerde lo sealado al respecto

    en 4.2.1e).

    http://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_2_1e.htm#Ref-1http://www.zator.com/Cpp/E4_2_1e.htm#Ref-1http://www.zator.com/Cpp/E4_2_1e.htm#Ref-1http://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E3_2_1c.htm
  • 5/26/2018 014 Programacion en c++

    25/55

    #include

    int main() {const int x = 35; // constante iniciada a 35int* ptr; // puntero a enteroptr = const_cast (&x); // Ok: (gracias al 'casting')cout

  • 5/26/2018 014 Programacion en c++

    26/55

    const int x = 23;int* iptr = const_cast (&x); // Ok!!

    2 cons_cast con punteros

    El cambio de atributo puede utilizarse con punteros, de forma que un puntero a-tipoX-constantepuede ser convertido en puntero a-tipoXy viceversa. El cambio tambin puederealizarse con un puntero a-tipoX-volatile.

    El puntero obtenido es idntico al original en todos los dems aspectos. Si la conversin tiene xitoel puntero resultante seala al mismo objeto que el original. Ejemplo:

    const int kte = 35;int* ptr;ptr = &kte; // Error!ptr = (int*) &kte; // modelado antiguo desaconsejadoptr = const_cast (&kte); // Ok:volatile int x = 45;

    ptr = &x; // Error!ptr = const_cast (&x); // Ok:

    As pues, este operador convierte un objeto (o referencia a objeto)constovolatileen un objeto (oreferencia) no-consto no-volatileque es idntico en lo dems al original.

    Es importante advertir que el operadorconst_castno cambia el tipodel operando, lo quesignifica que este operador no hace que una variable constante pueda volverse no-constante y veralterado su valor despus de aplicado el operador. Considere detenidamente el resultado obtenidoen el siguiente ejemplo, e intente llegar a una explicacin (recuerde lo sealado al respecto

    en 4.2.1e).

    #include

    int main() {const int x = 35; // constante iniciada a 35int* ptr; // puntero a enteroptr = const_cast (&x); // Ok: (gracias al 'casting')cout

  • 5/26/2018 014 Programacion en c++

    27/55

    4.9.9a El operad or co nst _cast

    1 Sinopsis:

    La palabra claveconst_castidentifica un operador de uso muy especfico: sirve para poner o

    quitar los atributosconstovolatilede un objeto. La sintaxis general es:

    const_cast< T > (arg)

    En la expresin anterior,Tyargdeben ser del mismo tipo, excepto en los atributos const(

    3.2.1c) yvolatile( 4.1.9).Tes el tipo al que se quiere convertir,arges el tipo de partida(ver ejemplo). El modelado es resuelto en tiempo de compilacin, y el resultado es del tipo T. Unasola expresinconst_castpuede poner o quitar el atributoconstovolatilea cualquier nmerode objetos.

    Ejemplo

    const int x = 10;int* iptr = &x; // Error!!

    Un intento de compilar las sentencias anteriores conduce a un error del compilador:

    invalid conversion from `const int*' to `int*'

    La razn es que se est intentando asignar la direccin de un int-consta un puntero-a-int, cuandose necesitara un puntero-a-int-const. Suponiendo que no queramos (o podamos) cambiar la

    definicin deiptr, el problema de la asignacin en la segunda lnea puede resolverse medianteun "casting" adecuado:

    const int x = 23;int* iptr = const_cast (&x); // Ok!!

    2 cons_cast con punteros

    El cambio de atributo puede utilizarse con punteros, de forma que un puntero a-tipoX-

    constantepuede ser convertido en puntero a-tipoXy viceversa. El cambio tambin puederealizarse con un puntero a-tipoX-volatile.

    El puntero obtenido es idntico al original en todos los dems aspectos. Si la conversin tiene xitoel puntero resultante seala al mismo objeto que el original. Ejemplo:

    const int kte = 35;int* ptr;ptr = &kte; // Error!ptr = (int*) &kte; // modelado antiguo desaconsejadoptr = const_cast (&kte); // Ok:volatile int x = 45;ptr = &x; // Error!ptr = const_cast (&x); // Ok:

    http://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E3_2_1c.htmhttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E4_1_9.htm#volatilehttp://www.zator.com/Cpp/E3_2_1c.htm
  • 5/26/2018 014 Programacion en c++

    28/55

    As pues, este operador convierte un objeto (o referencia a objeto)constovolatileen un objeto (oreferencia) no-consto no-volatileque es idntico en lo dems al original.

    Es importante advertir que el operadorconst_castno cambia el tipodel operando, lo quesignifica que este operador no hace que una variable constante pueda volverse no-constante y veralterado su valor despus de aplicado el operador. Considere detenidamente el resultado obtenidoen el siguiente ejemplo, e intente llegar a una explicacin (recuerde lo sealado al respecto

    en 4.2.1e).

    #include

    int main() {const int x = 35; // constante iniciada a 35int* ptr; // puntero a enteroptr = const_cast (&x); // Ok: (gracias al 'casting')cout

  • 5/26/2018 014 Programacion en c++

    29/55

    4 Descripcin

    es el tipo al que se convertir (resultado del modelado); puede ser cualquiera de los

    siguientes: puntero ( 4.2); referencia ( 4.2.3); tipo aritmtico ( 2.2.1)o enumeracin (

    4.7). Este operando se denomina tipodel modelado.

    arges el objeto cuyo tipo se desea convertir; debe ser asimilable al tipo de T(aqu no se

    pueden pedir imposibles); este operando se denominaargumentodel modelado. Ambos

    operandos, el argumento y el tipo (argy T), deben estar totalmente definidos en tiempo de

    compilacin.

    5 Si un tipo puede ser convertido en otro mediante algn sistema proporcionadoautomticamente por el lenguaje, utilizar la promocin explcita mediante este operador conduceexactamente al mismo resultado. Por ejemplo:

    int x = 10;float f1 = x; // promocin facilitada por el compilador

    float f2 = static_cast (x); // promicin explcita (preferible)

    6 Los enteros (int) pueden ser convertidos a enumeraciones (enum), pero tenga muy presenteque cualquier intento de promover el argumento a un valor que no sea un elemento de laenumeracin (enumerando), proporciona un resultado indefinido. Considere las dos salidas delejemplo compilado con C++Builder:

    #include

    int main() {enum COLOR { ROJO, VERDE, AZUL};COLOR c1 = VERDE;

    cout

  • 5/26/2018 014 Programacion en c++

    30/55

    El puntero nulo ( 4.2.1)es convertido a s mismo.

    El puntero a un objeto tipoXpuede ser promovido a puntero a cualquier otro tipoY, pero tenga encuenta que la mera promocin entre tipos de punteros puede ser motivo de problemas si los tiposequivalentes no estn alineados de forma similar.

    El resultado de la conversin esttica de un puntero es otra referencia al objeto original.

    Es posible convertir explcitamente, mediante una conversin esttica, un puntero a clase-Xapuntero a una clase-Y, si se dan las siguientes condiciones:

    Xes una clase base paraY.

    Existe una conversin sin ambigedades deYa X

    Xno es una clase-base virtual

    Un objeto puede ser convertido explcitamente a referencia-a-tipoX si un puntero a tal objeto puedeser explcitamente convertido a puntero-a-tipoX (tipoX*). El resultado de la conversin es un

    Lvalue. No son invocados constructores o funciones de conversin como resultado de unmodelado a una referencia.

    Un objeto o un valor puede ser convertido a un objeto clase, solo en el caso de que se hayandeclarado en la clase un constructor o un operador de conversin adecuados.

    Un puntero a miembro (de clase) puede ser convertido explcitamente en puntero a otro tipo demiembro solo si ambos tipos son punteros a miembros de la misma clase, o punteros a miembrosde dos clases, una de las cuales es derivada sin ambigedades de la otra.

    8 Convertir a referencia

    Cuando el tipo Tes una referencia, el resultado del modelado esttico es un Lvalue y se refiere a la

    expresin original, aunque este tipo de transformaciones puede resultar peligroso ( 4.2.3).

    4.9.9c El operador dynamic _cast

    Nota: El operador dynamic_castse refiere a conversiones de punteros y refencias aclases, por lo que su estudio exige un buen conocimiento previo de muchos conceptosrelacionados con ellas. Recomendamos al estudiante continuar con el estudio de las clases (

    4.11)antes de volver a este operador concreto.

    1 Sinopsis

    Como se ha indicado, este operador est reservado para conversiones de/hacia punteros yreferencias a clases, aunque exige que los punteros y referencias se refieran a clases de la mismajerarqua. De no cumplirse este condicin, la conversin es imposible y segn los casos, eloperador produce un resultado nulo o lanza una excepcin.

    Para entender los conceptos involucrados se hacen necesarias algunas puntualizacionessemnticas previas; recordemos que cuando se trata de clases emparentadas (pertenecientes auna jerarqua), hay que distinguir los casos en que las conversiones ("cast") entre punteros o

    http://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E4_2_3.htm#Modelado:http://www.zator.com/Cpp/E4_2_3.htm#Modelado:http://www.zator.com/Cpp/E4_2_3.htm#Modelado:http://www.zator.com/Cpp/E4_11.htmhttp://www.zator.com/Cpp/E4_11.htmhttp://www.zator.com/Cpp/E4_11.htmhttp://www.zator.com/Cpp/E4_2_3.htm#Modelado:http://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulo
  • 5/26/2018 014 Programacion en c++

    31/55

    referencias se realizan en sentido descendente ("Down") desde las clases-base hacia lasderivadas, o ascendente ("Up"), desde las clases-derivada hacia las superclases [1]. El primero esel sentido desde los antepasados a los descendientes; el segundo desde los descendientes a losancestros. Las conversiones en sentido descendente se denominan downcast, y lascontrarias upcast. Finalmente, cuando la conversin se da entre clases hermanas, sedenomina crosscast(modelado de cruce) [2].

    2 Sintaxis

    dynamic_cast (arg);

    3 Comentario

    El operando , denominado tipo, determina el resultado de la operacin, y debe ser un

    puntero ( 4.2.1f)o referencia ( 4.2.3)a una clase definida, o un puntero genrico void*(

    4.2.1d).

    El operando argrecibe el nombre de argumento, es el tipo que se quiere convertir, y debe seruna expresin que se resuelva en un puntero o una referencia (este operador no se puede aplicara otros tipos).

    El resultado del operador es un puntero o referencia del mismo valor que arg, apuntando o

    referenciando al mismo objeto, pero del tipo expresado por . Este operador se utiliza

    principalmente para realizar asignaciones que de otro modo no seran legales por diferencia detipos entre el Lvalue y el Rvalue.

    Para utilizar este operador es necesaria la capacidad RTTI (Runtime type

    identification 4.9.14).; As pues, los ejemplos en los que aparezca el

    operador dynamic_castdeben ser compilados con la opcin -RT[4]

    4 Ejemplos

    class Clase1 { ... } c1, *c1ptr;class Clase2 { ... } c2, *c2ptr = &c2, &ref2 = c2;...c1ptr = dynamic_cast(c2ptr); // L.4:Clase1& ref1 = dynamic_cast(ref2); // L.5:

    5 C++ exige que el donwcasto crosscastse realicen desde una clase polimrfica ( 4.11.8),

    de modo que argdebe ser de este tipo [3]. Sin embargo, el resultado de este modelado puede ser

    aplicado a un puntero o referencia a clase no polimrfica.

    En el ejemplo anterior, si Clase2no fuese polimrfica (no tuviese una funcin virtual), en L4 y L.5

    se obtendran sendos errores:

    Type 'Clase2' is not a defined class with virtual functions in...

    pero Clase1no tiene que serlo necesariamente para poder realizar las asignaciones anteriores.

    http://www.zator.com/Cpp/E4_9_9c.htm#[1]http://www.zator.com/Cpp/E4_9_9c.htm#[1]http://www.zator.com/Cpp/E4_9_9c.htm#[1]http://www.zator.com/Cpp/E4_9_9c.htm#[2]http://www.zator.com/Cpp/E4_9_9c.htm#[2]http://www.zator.com/Cpp/E4_9_9c.htm#[2]http://www.zator.com/Cpp/E4_2_1f.htmhttp://www.zator.com/Cpp/E4_2_1f.htmhttp://www.zator.com/Cpp/E4_2_1f.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_1d.htmhttp://www.zator.com/Cpp/E4_2_1d.htmhttp://www.zator.com/Cpp/E4_2_1d.htmhttp://www.zator.com/Cpp/E4_9_14.htm#Opci%C3%B3n%20-RThttp://www.zator.com/Cpp/E4_9_14.htm#Opci%C3%B3n%20-RThttp://www.zator.com/Cpp/E4_9_9c.htm#[4]http://www.zator.com/Cpp/E4_9_9c.htm#[4]http://www.zator.com/Cpp/E4_9_9c.htm#[4]http://www.zator.com/Cpp/E4_11_8.htmhttp://www.zator.com/Cpp/E4_11_8.htmhttp://www.zator.com/Cpp/E4_11_8.htmhttp://www.zator.com/Cpp/E4_9_9c.htm#[3]http://www.zator.com/Cpp/E4_9_9c.htm#[3]http://www.zator.com/Cpp/E4_9_9c.htm#[3]http://www.zator.com/Cpp/E4_9_9c.htm#[3]http://www.zator.com/Cpp/E4_11_8.htmhttp://www.zator.com/Cpp/E4_9_9c.htm#[4]http://www.zator.com/Cpp/E4_9_14.htm#Opci%C3%B3n%20-RThttp://www.zator.com/Cpp/E4_2_1d.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_1f.htmhttp://www.zator.com/Cpp/E4_9_9c.htm#[2]http://www.zator.com/Cpp/E4_9_9c.htm#[1]
  • 5/26/2018 014 Programacion en c++

    32/55

    6 Si es un puntero genrico void*, el argumento argdebe ser tambin un puntero. En estecaso, el puntero resultante puede acceder a cualquier elemento de la clase que sea el elementoms derivado de la jerarqua. Tal clase no puede ser clase-base para ninguna otra.

    7 Las conversiones de una clase derivada a clase-base (upcast) o de una clase derivada a otra(crosscast), se realiza como sigue: si Tes un puntero y ptres un puntero a una clase no-bsicade una jerarqua, el resultado es un puntero a la subclase nica. Las referencias son tratadas deforma similar: si Tes una referencia y ptres una referencia a una clase no bsica, el resultado esuna referencia a la subclase nica.

    8 La convesin upcast, de una clase derivada a una clase-base se resuelve en tiempo decompilacin. Por contra, la conversin downcast, de una clase-base a clase-derivada, o a travsde una jerarqua de clases, es resuelta en tiempo de ejecucin. Es decir:

    a.- Conversiones en tiempo de compilacin:

    subclase* superclase*

    subclase& superclase&b.- Conversiones en tiempo de ejecucin:

    subclase* superclase*

    subclase& superclase&

    El resultado es que, en caso de haberlos, los errores de los modelados a.sern anunciados por elcompilador. En cambio, los del tipo b.solo sern detectados en ejecucin.

    9 Si en la conversin de un puntero, el operador dynamic_cast< T> (ptr) tiene xito,proporciona un puntero sealando al mismo objeto que el argumento ptr, pero del tipo Trequerido.En cambio, si la conversin falla, el puntero obtenido es del tipo Tdeseado, pero se le asigna cero.

    En otras palabras, si el modelado de un puntero falla, se obtiene el puntero nulo( 4.2.1). Porcontra, si falla la conversin a una referencia, se lanza la excepcin bad_cast.

    Lo anterior significa que los modelados de este tipo con punteros deben ser comprobados

    siempre explcitamente para verificar que ptr!= 0 (ver lneas 16 y 22 del ejemplo ). En cambio,

    para verificar el xito del modelado de referencias basta el mecanismo de excepciones ( 1.6).

    10 Ejemplo

    En el programa que sigue se realizan modelados a travs de toda la jerarqua. Primero de realizael downcastde un puntero desde la clase base a la ms derivada, despus se realiza

    un upcastpara volver a otra base superior.

    #include #include

    class Base1 {virtual void f(void) { /* ... */ } // L.5:

    };

    class Base2 { };

    http://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulohttp://www.zator.com/Cpp/E1_6.htmhttp://www.zator.com/Cpp/E1_6.htmhttp://www.zator.com/Cpp/E1_6.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E4_9_9c.htmhttp://www.zator.com/Cpp/E1_6.htmhttp://www.zator.com/Cpp/E4_2_1.htm#Puntero%20nulo
  • 5/26/2018 014 Programacion en c++

    33/55

    class Derived : public Base1, public Base2 { };

    int main(void) { // ==========================try {Derived d, *pd;Base1* b1 = &d; // L.14:pd = dynamic_cast(b1); // L.15:if (pd != 0) {

    cout

  • 5/26/2018 014 Programacion en c++

    34/55

    En L.21, a b2(que es tipo Base2*) se le asigna la direccin sealada por b1. En esta asignacin

    ni la direccin ni el tipo son correctos. En primer lugar, b1seala a un objeto tipo Derived.

    Adems, b1es tipo Base1*. En consecuencia, se necesita un modelado al tipo de b2. Este

    modelado debe recorrer toda la jerarqua de clases, descendiendo (downcast) desde el

    tipo Base1*a la del tipo ms derivado Derived*; despus ascendiendo (upcast) desde el

    tipo derived*al tipo Base2*.

    En L.35 se anuncia la finalizacin normal del programa. En cambio, las terminaciones L.29 y L.33son terminaciones anormales, por lo que devuelven un valor distinto de cero al SO.

    11 Comprobacin de parentesco

    Dentro de las limitaciones sealadas (que se realice sobre clases polimrficas), la circunstancia de

    que el operador dynamic_castsolo funcione entre miembros de una jerarqua, es utilizado amenudo como un recurso para comprobar si dos objetos pertenecen o no a una misma familia.

    Por ejemplo, supongamos que tenemos un objeto apertenecientes a la clases A. Para comprobar

    si pertenece a una subclase de B(si Aderiva deB), podra utilizarse el siguiente cdigo:

    if (dynamic_cast(&a)) {/* A es derivada de B */

    } else {/* A no deriva de B */

    }

    4.9.9d Op erador reinterpr et_cast

    1 Sinopsis

    Las conversiones de tipo que se realizan con este operador podramos decir que son por la "fuerzabruta". Obligamos al compilador a aceptar un tipo de objeto por otro sin rechistar, por muy ilgicaque sea la transformacin (de ah el nombre).

    Ni que decir tiene que tales transformaciones son de lo ms peligroso y que deben ser realizadascon extrema precaucin. En realidad se suelen utilizar solo de forma temporal, para realizar

    determinadas transformaciones en los objetos [1]y volver a interpretarlos en su sentido original.Aunque en ocasiones est perfectamente justificado, su util izacin puede ser sntoma de unatcnica deficiente o de que el programador se est metiendo en problemas.

    2 Sintaxis

    reinterpret_cast (arg)

    3 Descripcin

    El operando (denominado tipo), determina el resultado de la conversin. Puede ser cualquiera

    de los tipos siguientes: puntero ( 4.2); referencia ( 4.2.3); tipo aritmtico ( 2.2.1); puntero

    a funcin ( 4.2.4), o puntero a miembro de clase ( 4.2.1g).

    http://www.zator.com/Cpp/E4_9_9d.htm#[1]http://www.zator.com/Cpp/E4_9_9d.htm#[1]http://www.zator.com/Cpp/E4_9_9d.htm#[1]http://www.zator.com/Cpp/E4_2.htmhttp://www.zator.com/Cpp/E4_2.htmhttp://www.zator.com/Cpp/E4_2.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E2_2_1.htmhttp://www.zator.com/Cpp/E2_2_1.htmhttp://www.zator.com/Cpp/E2_2_1.htmhttp://www.zator.com/Cpp/E4_2_4.htmhttp://www.zator.com/Cpp/E4_2_4.htmhttp://www.zator.com/Cpp/E4_2_4.htmhttp://www.zator.com/Cpp/E4_2_1g.htmhttp://www.zator.com/Cpp/E4_2_1g.htmhttp://www.zator.com/Cpp/E4_2_1g.htmhttp://www.zator.com/Cpp/E4_2_1g.htmhttp://www.zator.com/Cpp/E4_2_4.htmhttp://www.zator.com/Cpp/E2_2_1.htmhttp://www.zator.com/Cpp/E4_2_3.htmhttp://www.zator.com/Cpp/E4_2.htmhttp://www.zator.com/Cpp/E4_9_9d.htm#[1]
  • 5/26/2018 014 Programacion en c++

    35/55

    Es recomendable abandonar la antigua sintaxis (tipoX)expr, usando en su lugar el nuevo

    operador reinterpret_cast(expr) en todas aquellas conversiones que no sean

    seguras, o que sean dependientes de la implementacin.

    4 Ejemplo

    #include

    int main() { // =============int x = 10;float f = 20.5;int* ptx = &x; // puntero-a-enterofloat* ptf = &f; // puntero-a-float

    cout

  • 5/26/2018 014 Programacion en c++

    36/55

    La razn del error es obvia: el compilador interpreta el patrn de bits alojado a partir de la direccin0065FDFC como un tipo entero, cuando en realidad corresponde a un float, cuyo modelo de

    almacenamiento es totalmente distinto ( 2.2.4a). Bajo la ptica de un entero es el valor1101266944, mientras que interpretado como floates 20.5

    Ejemplo relativo a la conversin de tipo de un puntero a clase ( Ejemplo).

    5 Un puntero puede ser convertido explcitamente a un tipo numrico entero. Lo cual es lgico,dado que los punteros almacenan direcciones de memoria, que son magnitudes escalares enteras.

    Recprocamente, un argumento argentero puede ser convertido a un puntero. La conversin de

    un puntero en un entero y posterior conversin a puntero del tipo original, conduce al valor original.

    Ejemplo:

    #include

    int main() { // ==================int x, y;float f = 20.5;float* ptf = &f; // puntero-a-floatcout

  • 5/26/2018 014 Programacion en c++

    37/55

    class ::C { public: char ch; }; // L.14:C c = { 'a' }; // L.15:cout

  • 5/26/2018 014 Programacion en c++

    38/55

    puntero-a-funcin de otro tipo, y como estas transformaciones conducen fcilmente a resultadoserrneos.

    #include void func(void* v) { // L.2:int x = reinterpret_cast(v); // L.3:

    cout

  • 5/26/2018 014 Programacion en c++

    39/55

    Como hemos comentado en el apartado correspondiente ( 3.2.1a1), la principal razn de su usoes la portabilidad del cdigo, ya que existen versiones de estos sistemas para mquinas de 16, 32y 64 bits. Amn de sucesivas versiones de los mismos (W98, XP, NT, 2000 etc), as comoversiones "light", como Windows ME, para dispositivos mviles; telfonos, PDAs, Handhelds, etc.

    En ocasiones las funciones de la API devuelven tipos que son dependientes del contexto, por lo

    que al utilizarlas, debemos asegurarnos de emplear el modelado adecuado y de que este sea loms especfico posible. En casos extremos podemos encontrar incluso modelados sucesivos enuna misma expresin. Como botn de muestra, incluimos un ejemplo de utilizacin propuesto enuna publicacin de Microsoft [1].

    HBRUSH hbr;hbr = (HBRUSH)(UINT)SendMessage(hwnd, WM_CTLCOLOR, ..., ...);

    Tenga en cuenta que el tipoHBRUSHes puntero a un tipo especial de estructura;queWM_CTCOLORes un tipo numrico, y queUINTes tambin un tipo numrico(probablementeunsigned int).

    El documento seala que al utilizar este tipo de funciones, como SendMessage, antes de realizarel modelado al tipo necesario (HBRUSHen este caso), se debe realizar un modelado del valor

    devuelto aUINT. Esto es necesario para que el cdigo se portable, ya que el tamao de unpuntero ("handle") puede ser 16 o 32 bits, dependiendo de la versin de Windows, y el

    modelado(UINT)asegura que la conversin sea correcta (a la longitud adecuada).

    4.9.10 Op erador de prepr oces o

    1 Sinopsis

    Durante la primera fase de la compilacin de un programa, elpreprocesador( 1.4.1)realizaciertas modificaciones previas en el cdigo fuente. Se trata de una autntica traduccin del cdigosiguiendo unas pautas explicitadas en las denominadasdirectivas de preproceso[1]. Sonsentencias que se sitan normalmente al principio del cdigo fuente, aunque legalmente puedenaparecer en cualquier punto de la unidad de compilacin (tienen validez desde el punto deaparicin hasta el final del fichero).

    Por la razn anterior, se dice que estas directivas no respetan el mbito, por lo que (en especial

    los#define) pueden presentar efectos colaterales no deseados en puntos alejados de los que elprogramador ha previsto.

    2 Las directivas de preproceso se identifican por ser lneas precedidas por el smbolo#que es

    eloperador de preproceso. A menos que#est incluido en una cadena alfanumrica o en uncomentario, indica que lo que sigue es unadirectiva de preprocesoolnea de control.#puedeestar precedido o seguido por un separador (whitespace) excluyendo nueva lnea (NL).

    Las directivas de preprocesadononecesitan punto y coma (;) al final. Ejemplo:

    #include ; // L.1: permisible#include // L.2: mejor!!

    http://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E3_2_1a1.htmhttp://www.zator.com/Cpp/E4_9_9e.htm#[1]http://www.zator.com/Cpp/E4_9_9e.htm#[1]http://www.zator.com/Cpp/E4_9_9e.htm#[1]http://www.zator.com/Cpp/E1_4_1.htmhttp://www.zator.com/Cpp/E1_4_1.htmhttp://www.zator.com/Cpp/E1_4_1.htmhttp://www.zator.com/Cpp/E4_9_10.htm#[1]http://www.zator.com/Cpp/E4_9_10.htm#[1]http://www.zator.com/Cpp/E4_9_10.htm#[1]http://www.zator.com/Cpp/E4_9_10.htm#[1]http://www.zator.com/Cpp/E1_4_1.htmhttp://www.zator.com/Cpp/E4_9_9e.htm#[1]http://www.zator.com/Cpp/E3_2_1a1.htm
  • 5/26/2018 014 Programacion en c++

    40/55

    Nota: la lnea 1, aunque permisible, puede dar un aviso de compilacin con algunos compiladores.Concretamente el compilador Borland C++ 5.5 compila sin ningn aviso, mientras que MS Visual

    C++ 6.0 muestra un "Warning" ( 1.4):

    Unexpected tokens following preprocessor directive - expected anewline...

    Evidentemente el token al que se refiere es el punto y coma final, que es innecesario.

    3 El Estndar C++ soporta las directivas que se indican a continuacin; todas ellas tienen un

    sentido definido. La ltima,#pragma, se ha previsto para que cada fabricante de compilador puedainventar las suyas particulares sin que interfieran con las de otras implementaciones (si uncompilador encuentra una de estas directivas y no sabe que hacer con ella, sencillamente laignora). El sentido de las dems se indica en los epgrafes correspondientes.

    #(directiva nula)

    #define

    #error

    #if, #elif, #else, #endif

    #ifdef, #ifndef

    #import

    #include

    #line

    #undef

    #pragma

    4 # Directiva nula

    La directiva nula consiste en una lnea con un solo carcter#. Este lnea es ignorada totalmente.

    Direct iva #define

    1 Sinopsis

    La directiva #definedefine una macro. Las macros proporcionan un mecanismo de reemplazo de

    tokens ( 3.2)con o sin una serie de parmetros formales (parecidos a las funciones). Estasimilitud con las funciones hace que en ocasiones sirvan para una especie de sustitucin inline(

    4.4.6b), aunque esta prctica presenta sus riesgos .

    2 Sintaxis

    #define macro_identificador

    3 Comentario

    http://www.zator.com/Cpp/E1_4.htm#Warningshttp://www.zator.com/Cpp/E1_4.htm#Warningshttp://www.zator.com/Cpp/E1_4.htm#Warningshttp://www.zator.com/Cpp/E3_2.htmhttp://www.zator.com/Cpp/E3_2.htmhttp://www.zator.com/Cpp/E3_2.htmhttp://www.zator.com/Cpp/E4_4_6b.htmhttp://www.zator.com/Cpp/E4_4_6b.htmhttp://www.zator.com/Cpp/E4_4_6b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_9_10b.htmhttp://www.zator.com/Cpp/E4_4_6b.htmhttp://www.zator.com/Cpp/E3_2.htmhttp://www.zator.com/Cpp/E1_4.htm#Warnings
  • 5/26/2018 014 Programacion en c++

    41/55

  • 5/26/2018 014 Programacion en c++

    42/55

    Valor x == 10Valor x == 13Valor x == 10

    los nombres definidos en las macros noestn sujetos a las reglas de visibilidad de los

    subespacios de nombres ( 4.1.11), lo que las hace altamente peligrosas, ya que el mecanismode sustitucin de tokens "arrasa" a lo largo de todo el cdigo, efectuando cuantas sustitucionessean congruentes con su definicin. A veces en sitios donde no pensbamos que lo hara y que, deotro modo, estaran relativamente a salvo de colisiones. Por ejemplo, en el interior de clases. Estaes una de las razones por las que se prefiere utilizar maysculas en los macro_identificadores;para disminuir la posibilidad de concordancias fortuitas. Por ejemplo, considere el siguiente cdigo:

    ...{#define min -1#define max 127

    A a = foo(a, min, max); // L.m...B res = result (x, y, min); // L.n

    }... /* ms adelante en un punto alejado */int max = getmax(a, b); // L.k

    En este caso, el programador ha previsto los #defineminy maxpara mayor legibilidad y facilidad

    de modificacin del cdigo, como en las sentencias L.my L.n, pero quizs ms adelante,

    en L.kutiliza dicho nombre para definir una variable olvidando los #define anteriores y que estos

    tienen validez desde el punto de su definicin hasta el final, con independencia de que hayan sidoincluidos dentro del mbito definido por los corchetes { }.

    Como resultado de lo anterior, entre otras medidas, se considera buena prctica anular su efecto

    con #undef( 4.9.10j)inmediatamente despus de que dejen de ser necesarios. Por ejemplo, laforma correcta del cdigo anterior podra ser:

    ...{#define min -1#define max 127

    A a = foo(a, min, max);...B res = result (x, y, min);

    #undef min#undef max}

    ...int max = getmax(a, b);

    Sin embargo, un programador C++ de lite escribira:

    ...{

    enum { min = -1, max = 127 };A a = foo(a, min, max);

    http://www.zator.com/Cpp/E4_1_11.htmhttp://www.zator.com/Cpp/E4_1_11.htmhttp://www.zator.com/Cpp/E4_1_11.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_1_11.htm
  • 5/26/2018 014 Programacion en c++

    43/55

    ...B res = result (x, y, min);

    }...

    3.3 Cualquier carcter encontrado en el cuerpo de la macro aparecer en la macro-expansin. Elcuerpo de la macro termina en el primer carcter de nueva lnea NL (10) que no est precedido de(\). Cualquier secuencia de espacios y/o comentarios en la lnea de control, son reemplazados porun solo carcter de espacio.

    3.4 Un cuerpo de macro vaco est permitido. Ejemplo:

    #define VACIO

    Su efecto es doble, de forma que puede utilizarse con dos finalidades distintas, segn se trate delcdigo fuente, o de la accin de otros elementos del preprocesador.

    En lo que respecta a la lgica del preprocesador, si se encuentra una expresin como la

    anterior, a la que falta la secuencia-de-tokens, el macro_identificadoradopta elvalor 1, que es cierto (true). Este tipo de expresiones suele utilizarse en conjuncin con la

    directivas de preproceso #ifdefe #ifndef( 4.9.10e), que interrogan si un macro

    identificador est definido (es cierto) o no lo est (es falso).

    En lo que respecta al cdigo fuente, la presencia de un cuerpo de macro vaco, suponela eliminacin de cada macro-identificador del cdigo fuente, ya que cada ocurrencia

    de VACIOes sustituido por un nulo.

    3.5 Despus de cada macro-expansin se realiza una nueva exploracin del cdigo para ver siexisten nuevas expansiones, lo que permite la existencia de expansiones anidadas, ya que el textodespus de una expansin puede contener macro-identificadores que puedan sufrir otra expansin

    subsiguiente. Si la macro se expande a algo que parezca una directiva de preprocesado, esta noser reconocida por el preprocesador.

    Ejemplos

    #define NIL ""#define GETSTD #include #define forever for (;;); // Loop infinito#define max(A, B) ((A) > (B) ? (A) : (B))

    La ltima directiva origina que una lnea en el fuente tal como:

    x = max (p+q, r+s);

    ser transformada por el preprocesador en [3]:

    x = ((p+q) > (r+s) ? (p+q) : (r+s));

    4 Como el lector puede suponer, las caractersticas de los define, combinadas con las directivas

    de preprocesado condicionales #if y #else( 4.9.10d), representan un cmulo de posibilidadespara el programador.

    http://www.zator.com/Cpp/E4_9_10e.htmhttp://www.zator.com/Cpp/E4_9_10e.htmhttp://www.zator.com/Cpp/E4_9_10e.htmhttp://www.zator.com/Cpp/E4_9_10b.htm#[3]http://www.zator.com/Cpp/E4_9_10b.htm#[3]http://www.zator.com/Cpp/E4_9_10b.htm#[3]http://www.zator.com/Cpp/E4_9_10d.htmhttp://www.zator.com/Cpp/E4_9_10d.htmhttp://www.zator.com/Cpp/E4_9_10d.htmhttp://www.zator.com/Cpp/E4_9_10d.htmhttp://www.zator.com/Cpp/E4_9_10b.htm#[3]http://www.zator.com/Cpp/E4_9_10e.htm
  • 5/26/2018 014 Programacion en c++

    44/55

    Ejemplo

    // # define SP 1// # define US 1// # define FR 1#if SP

    # define ERRN "Error no recuperable en linea:"#elif US# define ERRN "Unrecoverable Error in line:"

    #elif FR# define ERRN "Error ne pas recuperable en line:"

    #endif

    Para cambiar el lenguaje de los mensajes en que aparezca ERRNen el fuente, solo hay que quitar

    el comentario a la lnea correspondiente al idioma que queremos. Con este sencillo truco, un solofuente puede servir para diversas versiones idiomticas del programa[1].

    5 Limitaciones

    La macro-expansin adolece de las siguientes limitaciones:

    Cualquier ocurrencia del macro-identificador dentro de cadenas alfanumricas, constantescarcter o comentarios en el cdigo fuente son ignorados. Ejemplo:

    #define pi 3.14159;...char* ptr = "Mostrar el valor de pi con decimales\n";cout

  • 5/26/2018 014 Programacion en c++

    45/55

    Las macros tienen su sitio y su justificacin, pero tambin sus riesgos e inconvenientes. En generalno se aconseja demasiado su uso y menos su abuso, porque dan lugar a un cdigo difcil de leer.

    Adems, cuando se utiliza como una especie de sustitucin inline( 4.4.6b)de funciones,presenta un inconveniente importante y es que con la macro no se realiza comprobacin estticade tipos (uno de los mecanismos de prevencin de errores de C++). Es decir, no existecomprobacin de que el tipo de los parmetros formales coincide con los argumentos actuales (

    4.4.5), lo que puede generar errores difciles de depurar. Adems existe el riesgo de efectoscolaterales indeseados, en especial cuando el argumento actual es evaluado ms de una vez.

    Como ejemplo de lo anterior, considere el siguiente programa que utiliza sucesivamente lafuncin cuboy una macro CUBO, para calcular la potencia 3 de una cantidad.

    int cubo(int x) { // funcinreturn x*x*x;

    }

    #define CUBO(x) ( (x)* (x) * (x) ) // Macro sustitucin (ver nota )...int b = 0, a = 3;b = cubo(a++); // L.7: clculo mediante funcina = 3;b = CUBO(a++); // L.9: sustitucin y asignacin posterior

    En el primer caso, L.7: el argumento actual pasado a la funcin es 3, de forma que b = 3*3*3 ==

    27; a continuacin, aes incrementado, con lo que: a == 4.

    En el segundo caso, L.9: CUBOes sustituido por la macro correspondiente, por lo que la sentencia

    quedara como:

    b = ((a++)*(a++)*(a++)); // L.9-bis

    el resultado es que b = 3*3*3 == 27, pero despus, asufre tres incrementos unitarios

    sucesivos, de forma que finalmente a == 6.

    Observe que en este tipo de expresiones el parntesis no puede estar separado de la macro:

    #define CUBO(x) ( (x)* (x) * (x) ) // Ok.#define CUBO (x) ( (x)* (x) * (x) ) // Error!!

    7 Las macros en la prctica

    Como resultado de todo esto, aunque estn ah para usarlas, la mayora de los textos y autoressealan que las macros, otrora bastante populares en C, son un recurso obsoleto que puede y

    debe ser evitado. No obstante, los ficheros de cabecera de los compiladores suelen estar plagadosde macros, en especial para declarar constantes manifiestas ( 1.4.1a). Por ejemplo:

    #define TABSIZE 100...int table[TABSIZE];

    Sin embargo, la mayora de las veces los ficheros de cabecera hacen uso de "defines" bastantesofisticadas. Por ejemplo, los que siguen pertenecen al compilador MS Visual C++:

    http://www.zator.com/Cpp/E4_4_6b.htm#Sustituci%C3%B3n%20inlinehttp://www.zator.com/Cpp/E4_4_6b.htm#Sustituci%C3%B3n%20inlinehttp://www.zator.com/Cpp/E4_4_6b.htm#Sustituci%C3%B3n%20inlinehttp://www.zator.com/Cpp/E4_4_5.htmhttp://www.zator.com/Cpp/E4_4_5.htmhttp://www.zator.com/Cpp/E4_4_5.htmhttp://www.zator.com/Cpp/E1_4_1a.htmhttp://www.zator.com/Cpp/E1_4_1a.htmhttp://www.zator.com/Cpp/E1_4_1a.htmhttp://www.zator.com/Cpp/E1_4_1a.htmhttp://www.zator.com/Cpp/E4_4_5.htmhttp://www.zator.com/Cpp/E4_4_6b.htm#Sustituci%C3%B3n%20inline
  • 5/26/2018 014 Programacion en c++

    46/55

  • 5/26/2018 014 Programacion en c++

    47/55

  • 5/26/2018 014 Programacion en c++

    48/55

    Resultado z4 == : 3Resultado z5 == : 6

    9 Doble almohadilla ##

    los caracteres #y ##se usan tambin para realizar sustitucin y asociacin de tokens durante lafase de anlisis del preprocesado. Este par de smbolos se conocen como tokenadhesivo("Token paste"), porque permiten pegar o asociar dos tokens situados entre las dosalmohadilla ( puede haber espacios opcionales en cada extremo).

    En estos casos, el preprocesador elimina los espacios y la doble almohadilla, combinando los dostokens en uno solo. Esto puede usarse para construir identificadores. Por ejemplo, dada ladefinicin:

    #define VAR(i, j) i##j

    la llamada VAR(x, 6)se expande a x6.

    Nota: este es el sistema nuevo, que reemplaza al antiguo (no estndar) mtodo de utilizar:

    #define VAR(i, j) (i/**/j)

    Ejemplo

    #define WCHAR( X ) L##X#define WCHPT wchar_t*

    la expresin:

    WCHPT cptr = WCHAR("Hola mundo");

    se transforma en:

    wchar_t* cptr = L"Hola mundo";

    En la pgina adjunta se muestra un ejemplo ms elaborado de uso de esta directiva ( 4.9.10b1).

    Direct iva #error

    1 Sintaxis

    #error mensaje-de-error

    2 Descripcin

    La directiva #errorgenera el siguiente mensaje:

    Error: filename line# : Error directive: mensaje-de-error

    http://www.zator.com/Cpp/E4_9_10b1.htmhttp://www.zator.com/Cpp/E4_9_10b1.htmhttp://www.zator.com/Cpp/E4_9_10b1.htmhttp://www.zator.com/Cpp/E4_9_10b1.htm
  • 5/26/2018 014 Programacion en c++

    49/55

    Esta directiva se suele incluir en sentencias de preprocesado condicional para detectar algunacondicin indeseada en tiempo de compilacin. Generalmente dicha condicin debe ser falsa, perosi resultara cierta, se desea que el compilador muestre un mensaje de error y el proceso sedetenga. Esto puede conseguirse incluyendo una directiva #errordentro de una sentenciacondicional que resulte cierta en caso de error.

    3 Ejemplo

    El caso comentado en la directiva define ( #define)podra complementarse de la forma que seindica:

    // # define Sp 1// # define Us 1// # define Fr 1#if Sp

    # define ERRN "Error no recuperable en linea:"#elif Us

    # define ERRN "Unrecoverable Error in line:"

    #elif Fr# define ERRN "Error ne pas recuperable en line:"

    #else# error "Seleccionar alguna de las opciones de lenguaje"

    #endif

    Directiv as #if, #elif, #else, #endif

    1 Sinopsis

    C++ ofrece la posibilidad de compilacin condicional mediante la inclusin de ciertas directivas que

    controlan el comportamiento del preprocesador, de forma que este puede ignorar o compilardeterminadas lneas del cdigo en funcin de ciertas condiciones que son evaluadas durante elpreproceso.

    2 Sintaxis

    #ifk-expresion-1

  • 5/26/2018 014 Programacion en c++

    50/55

  • 5/26/2018 014 Programacion en c++

    51/55

    El ejemplo siguiente muestra unas sentencias de compilacin condicional en funcin del valor de la

    constante simblica DLEVELque se supone ha sido definida previamente.

    #if DLEVEL > 5#define SIGNAL 1

    #if STACKUSE == 1#define STACK 200#else#define STACK 100

    #endif#else#define SIGNAL 0#if STACKUSE == 1#define STACK 100

    #else#define STACK 50

    #endif#endif#if DLEVEL == 0#define STACK 0

    #elif DLEVEL == 1#define STACK 100

    #elif DLEVEL > 5display( debugptr );

    #else#define STACK 200

    #endif

    El primer bloque #if(primeras 15 lneas), contiene dos series dedirectivas #if, #elsey #endifanidadas en l. La primera se procesa si es cierta la

    condicin DLEVEL > 5. En caso contrario se procesa la serie situada despus del #else.

    El resto de lneas del ejemplo se utiliza para establecer el valor de la constante STACKa 0, 100 o

    200 en funcin del valor de la constante DLEVEL, pero si su valor es mayor que 5, STACKqueda

    indefinida, y en su lugar se compila una invocacin a la

    funcin displayutilizando debugptrcomo argumento.

    5 Operador defined

    Tanto Borland C++ como MS VC++ disponen de este operador [1]que solopuede ser utilizado enconjuncin con las directivas #ify #elif. Admite dos formas de sintaxis, una de ellas con aspecto defuncin:

    #if defined( )#if defined#elif defined( )#elif defined

    5.1 Descripcin

    http://www.zator.com/Cpp/E4_9_10d.htm#[1]http://www.zator.com/Cpp/E4_9_10d.htm#[1]http://www.zator.com/Cpp/E4_9_10d.htm#[1]http://www.zator.com/Cpp/E4_9_10d.htm#[1]
  • 5/26/2018 014 Programacion en c++

    52/55

  • 5/26/2018 014 Programacion en c++

    53/55

    con #undefX( 4.9.10i), con lo que podemos controlar a voluntad la zonas de cdigo en que seconsidera definido e indefinido.

    Nota: La existencia semntica del identificador (el hecho de que est definido o no), esindependiente del valor concreto que pudiera tener asignado. Como veremos a continuacin,incluso si se le asigna el valor nulo, el identificador se considera definido.

    Un identificador definido como NULLes considerado definido. Por ejemplo:

    #define nulo NULL

    3 Ejemplo

    #define isSp // Flag Espaol/Ingls#ifdef isSp

    # include "ztr--Sp.CH"#define VComP "C.000621Sp"

    #else

    # include "ztr--Us.CH"#define VComP "C.000621Us"

    #endif........#undef isSp // A partir de aqu, isSp se considera indefinido........

    4 Directivas de guarda

    Tenga en cuenta que el lenguaje C++ es muy proclive a que se cometan cierto tipo de errores al

    trabajar con ficheros de cabecera (es seguro que ocurrir a menudo). Por ejemplo, supongamosque tenemos una clase denominada Hotelque utiliza una clase denominada Suitey que cada

    una de estas clases utiliza el mismo fichero de cabecera, por ejemplo ZonasHotel.h[2]. En estecaso es ms que posible que recibamos un error de compilacin del tipo

    ... Multiple declaration for 'FILE' ...

    indicndonos que estamos redefiniendo los smbolos de ZonasHotel.hla segunda vez que lacabecera es incluida.

    Una solucin es disponer el cdigo como se indica:

    #ifndef zonasH#include "ZonasHotel.h"

    #define zonasH // Nota [3]#endif... // aqu sigue el cdigo del programa

    Sin embargo, esta disposicin tiene el inconveniente de que tenemos que acordarnos de

    definir zonasHcada vez que vayamos a incluir la cabecera. Si lo olvidamos, volver a producirse el

    error (esto es muy probable en ambientes donde trabajan varios programadores en el mismoproyecto).

    http://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10j.htmhttp://www.zator.com/Cpp/E4_9_10e.htm#[2]http://www.zator.com/Cpp/E4_9_10e.htm#[2]http://www.zator.com/Cpp/E4_9_10e.htm#[2]http://www.zator.com/Cpp/E4_9_10e.htm#[3]http://www.zator.com/Cpp/E4_9_10e.htm#[3]http://www.zator.com/Cpp/E4_9_10e.htm#[3]http://www.zator.com/Cpp/E4_9_10e.htm#[3]http://www.zator.com/Cpp/E4_9_10e.htm#[2]http://www.zator.com/Cpp/E4_9_10j.htm
  • 5/26/2018 014 Programacion en c++

    54/55

  • 5/26/2018 014 Programacion en c++

    55/55

    // ZonasHotel.h Ejemplo de fichero de cabecera

    #if !defined( ZONASH )#define ZONASH

    class MiClase {...

    };

    #endif