Conversiones estándar de C ++

Conversiones estándar de C ++
Hay dos tipos de entidades en C ++, los tipos fundamentales y los tipos de compuestos. Los tipos fundamentales son los tipos escalar. Los tipos de compuestos son el resto de los tipos de entidad. La conversión puede tener lugar de un tipo de entidad a otro tipo apropiado. Considere el siguiente programa: #Include
#incluir
usando el espacio de nombres STD;
int main ()

int rt1 = sqrt (5);
int rt2 = sqrt (8);
cout<regresar 0;

La salida es 2, 2, lo que significa que el programa ha devuelto la raíz cuadrada de 5 como 2 y la raíz cuadrada de 8 también como 2. Entonces, las dos primeras declaraciones en el principal() la función ha frenado las respuestas de la raíz cuadrada de 5 y la raíz cuadrada de 8. Este artículo no discute pisos o techo en C++. Más bien, este artículo analiza la conversión de un tipo C ++ a otro tipo C ++ apropiado; indicando cualquier aproximación en el valor realizado, pérdida de precisión o restricción agregada o eliminada. El conocimiento básico de C ++ es un requisito previo para comprender este artículo.

Contenido del artículo

  • Conversiones integrales
  • Conversiones de punto flotante
  • Conversiones de integrales flotantes
  • Clasificación de conversión entera
  • Promociones integrales
  • Conversiones aritméticas habituales
  • Promoción de punto flotante
  • Conversiones de puntero
  • Funcionar a las conversiones de puntero
  • Conversiones booleanas
  • Lvalue, pralupa y xvalue
  • Xvalor
  • Conversiones de Lvalue-to-Ralue
  • Conversiones de matriz a punto
  • Conversiones de función al punto
  • Conversiones de materialización temporal
  • Conversiones de calificación
  • Conclusión

Conversiones integrales

Las conversiones integrales son conversiones enteros. Unsigned Integers incluyen "Unsigned Char", "Unsigned Short int", "Unsigned int", "Unsigned Long int" y "Unsigned Long Long int."Los enteros firmados correspondientes incluyen" Char firmado "," Short int "," int "," Long int "y" Long Long int."Cada tipo int debe mantenerse en tantos bytes como su predecesor. Para la mayoría de los sistemas, un tipo de entidad se puede convertir a un tipo correspondiente sin ningún problema. El problema ocurre al convertirse de un tipo de rango más grande a un tipo de rango más pequeño, o al convertir un número firmado en un número sin firmar correspondiente.

Cada compilador tiene un valor máximo que puede tomar para el corto int. Si un número más alto que ese máximo, destinado a un int, se asigna a la int -int -int, el compilador seguirá algún algoritmo y devolverá un número dentro del rango del intento corto. Si el programador tiene suerte, el compilador advertirá problemas con el uso de una conversión inapropiada. La misma explicación se aplica a las conversiones de otros tipos de int.

El usuario debe consultar la documentación del compilador para determinar los valores limitantes para cada tipo de entidad.

Si se debe convertir un número de INT de corta negativo negativo en un número INT de corto sin firmar, el compilador seguirá algún algoritmo y devolverá un número positivo dentro del rango del corto intento sin firmar. Este tipo de conversión debe evitarse. La misma explicación se aplica a las conversiones de otros tipos de int.

Cualquier número entero, excepto 0, se puede convertir a Boolean True. 0 se convierte en falso booleano. El siguiente código ilustra esto:

int a = -27647;
flotante b = 2.5;
int c = 0;
bool a1 = a;
bool b1 = b;
bool c1 = c;
cout<cout<cout<La salida es:

1
1
0

1 significa verdadero, y 0 significa falso en la salida

Conversiones de punto flotante

Los tipos de puntos flotantes incluyen "Float", "Double" y "Long Double."Los tipos de puntos flotantes no se agrupan en firmados y sin firmar, como enteros. Cada tipo puede tener un número firmado o sin firmar. Un tipo de punto flotante debe tener al menos la misma precisión que su predecesor. Es decir, "largo doble" debe tener una precisión igual o mayor para "duplicar" y "duplicar" debería tener una precisión igual o mayor para "flotar."

Recuerde que el rango de un tipo de punto flotante no es continuo; más bien, está en pequeños pasos. Cuanto mayor sea la precisión del tipo, más pequeños son los pasos y mayor será el número de bytes para almacenar el número. Entonces, cuando un número de punto flotante se convierte de un tipo de precisión más bajo a un tipo de precisión más alto, el programador debe aceptar un aumento falso en la precisión y un posible aumento en el número de bytes para el almacenamiento de números. Cuando un número de punto flotante se convierte de un tipo de precisión más alto a un tipo de precisión más bajo, el programador debe aceptar una pérdida en precisión. Si el número de bytes para el almacenamiento numérico debe reducirse, entonces el compilador seguirá algún algoritmo y devolverá un número como sustituto (que probablemente no sea lo que el programador quiere). Además, tenga en cuenta los problemas fuera de rango.

Conversiones de integrales flotantes

Un número de punto flotante se convierte en un entero truncando la parte fraccional. El siguiente código ilustra esto:

flotante F = 56.953;
int i = f;
cout<La salida es 56. Los rangos para el flotador y el entero deben ser compatibles.

Cuando un entero se convierte en un flotador, el valor que se muestra como un flotador es el mismo que se escribió como un entero. Sin embargo, el equivalente de flotación podría ser el valor exacto o tener una ligera diferencia fraccional que no se muestra. La razón de la diferencia fraccional es que los números de punto flotante están representados en la computadora en pequeños pasos fraccionales, por lo que representar exactamente al entero sería una coincidencia exactamente. Entonces, aunque el entero que se muestra como un flotador es el mismo que se escribió, la pantalla puede ser una aproximación de lo que se almacena.

Clasificación de conversión entera

Cualquier tipo entero tiene un rango que se le haya dado. Esta clasificación ayuda en la conversión. La clasificación es relativa; Las rangos no están en niveles fijos. Excepto por Char y Char firmado, no hay dos enteros firmados tienen el mismo rango (suponiendo que Char esté firmado). Los tipos de enteros sin firmar tienen la misma clasificación que sus tipos enteros firmados correspondientes. La clasificación es la siguiente:

  • Suponiendo que Char está firmado, entonces Char y firmado Char tienen el mismo rango.
  • El rango de un tipo entero firmado es mayor que el rango de un tipo entero firmado de un número menor de bytes de almacenamiento. Por lo tanto, el rango de INT largo de largo firmado es mayor que el rango de INT largo firmado, que es mayor que el rango de INT firmado, que es mayor que el rango de INT de corto firmado, que es mayor que el rango de char firmado.
  • El rango de cualquier tipo entero sin firmar es igual al rango del tipo entero firmado correspondiente.
  • El rango de char sin firmar es igual al rango de char firmado.
  • Bool tiene el menor rango; su rango es menor que el de Char firmado.
  • char16_t tiene el mismo rango que el corto int. Char32_t tiene el mismo rango que el int. Para el compilador G ++, wchar_t tiene el mismo rango que el int.

Promociones integrales

Promociones integrales son promociones enteros. No hay ninguna razón por la cual un entero de menos bytes no pueda ser representado por un entero de mayores bytes. Las promociones enteras se ocupan de todo lo que sigue:

  • Se puede convertir un intento corto firmado (dos bytes) a un int (cuatro bytes) firmado (cuatro bytes). Un corto sin firmar (dos bytes) se puede convertir en un int no firmado (cuatro bytes). NOTA: Convertir un intento corto en un int o un intento largo largo o un largo INT conduce a un desperdicio de bytes de almacenamiento (ubicación del objeto) y un desperdicio de memoria. Bool, Char16_t, Char32_t y Wchar_t están exentos de esta promoción (con el compilador G ++, Char32_t y Wchar_t tienen el mismo número de bytes).
  • Con el compilador G ++, un tipo Char16_T se puede convertir a un tipo int Intro o un tipo INT sin firmar; Un tipo Char32_T se puede convertir a un tipo int Intro o un tipo INT sin firmar; y un tipo wchar_t se puede convertir a un tipo ints INT firmado o sin firmar.
  • Un tipo de bool se puede convertir a un tipo int. En este caso, True se convierte en 1 (cuatro bytes) y falso se convierte en 0 (cuatro bytes). Int puede ser firmado o firmado.
  • La promoción entera también existe para el tipo de enumeración no cacada - ver más tarde.

Conversiones aritméticas habituales

Considere el siguiente código:

flotante f = 2.5;
int i = f;
cout<El código se compila sin indicar ninguna advertencia o error, dando la salida de 2, que probablemente no sea lo que se esperaba. = es un operador binario porque toma un operando izquierdo y derecho. Considere el siguiente código:

int i1 = 7;
int i2 = 2;
flotante flt = i1 / i2;
cout<La salida es 3, Pero esto está mal; se supone que iba a ser 3.5. El operador de división, /, también es un operador binario.

C ++ tiene conversiones aritméticas habituales que el programador debe saber para evitar errores en la codificación. Las conversiones aritméticas habituales en operadores binarios son las siguientes:

  • Si cualquiera de los operando es del tipo "Doble largo", entonces el otro se convertirá en Double largo.
  • Más, si cualquiera de los operando es doble, el otro se convertirá en doble.
  • Más, si cualquiera de los operando es flotante, el otro se convertirá en flotación. En el código anterior, el resultado de i1/i2 es oficialmente 2; Por eso FLT es 2. El resultado del binario, /, se aplica como el operando correcto al operador binario, =. Entonces, el valor final de 2 es un flotador (no un int).

De lo contrario, la promoción de enteros se llevaría a cabo de la siguiente manera:

  • Si ambos operandos son del mismo tipo, entonces no se realiza una conversión adicional.
  • De lo contrario, si ambos operandos se firman tipos enteros o ambos son tipos enteros sin firmar, entonces el operando del tipo con el rango entero más bajo se convertirá en el tipo de operando con el rango más alto.
  • De lo contrario, si se firma un operando y el otro no está firmado, y si el tipo de operando sin firmar es mayor o igual al rango del tipo de operando firmado, y si el valor del operando firmado es mayor o igual a cero, entonces cero, entonces El operando firmado se convertirá al tipo de operando sin firmar (con el rango tomado en consideración). Si el operando firmado es negativo, entonces el compilador seguirá un algoritmo y devolverá un número que puede no ser aceptable para el programador.
  • De lo contrario, si un operando es un tipo entero firmado y el otro es un tipo entero sin firmar, y si todos los valores posibles del tipo de operando con el tipo de entero sin firmar pueden representarse mediante el tipo entero firmado, entonces el tipo entero sin firmar será convertirse en el tipo de operando del tipo entero firmado.
  • De lo contrario, los dos operandos (un char y un bool, por ejemplo) se convertirían en el tipo de entero sin firmar.

Promoción de punto flotante

Los tipos de puntos flotantes incluyen "Float", "Double" y "Long Double."Un tipo de punto flotante debe tener al menos la misma precisión que su predecesor. La promoción de punto flotante permite la conversión de flotador a doble o de doble a largo.

Conversiones de puntero

Un puntero de un tipo de objeto no se puede asignar a un puntero de un tipo de objeto diferente. El siguiente código no compilará:

int id = 6;
int* intptr = &id;
FLOAT IDF = 2.5;
Float* floatptr = &idf;
intptr = floatptr; // Error aquí

Un puntero nulo es un puntero cuyo valor de dirección es cero. No se puede asignar un puntero nulo de un tipo de objeto a un puntero nulo de un tipo de objeto diferente. El siguiente código no compilará:

int id = 6;
int* intptr = &id;
intptr = 0;
FLOAT IDF = 2.5;
Float* floatptr = &idf;
floatptr = 0;
intptr = floatptr; // Error aquí

No se puede asignar una constante de puntero nulo de un tipo de objeto a una constante de puntero nulo de un tipo de objeto diferente. El siguiente código no compilará:

int id = 6;
int* intptr = &id;
int* const intpc = 0;
FLOAT IDF = 2.5;
Float* floatptr = &idf;
flotante* const floatpc = 0;
intpc = floatpc; // Error aquí

Un puntero nulo puede recibir un valor de dirección diferente para su tipo. El siguiente código ilustra esto:

FLOAT IDF = 2.5;
float* floatptr = 0;
floatptr = &idf;
cout<<*floatPtr<<'\n';

La salida es 2.5.

Como se esperaba, una constante de puntero nulo no se puede asignar ningún valor de dirección de su tipo. El siguiente código no compilará:

FLOAT IDF = 2.5;
flotante* const floatpc = 0;
floatpc = &idf; // Error aquí

Sin embargo, una constante de puntero nulo se puede asignar a un puntero ordinario, pero del mismo tipo (esto es de esperar). El siguiente código ilustra esto:

FLOAT IDF = 2.5;
flotante* const floatpc = 0;
Float* Floatpter = &idf;
floatpter = floatpc; //DE ACUERDO
cout << floatPter << '\n';

La salida es 0.

Dos valores de puntero nulo del mismo tipo comparan (==) igual.

Se puede asignar un puntero a un tipo de objeto a un puntero a Void. El siguiente código ilustra esto:

FLOAT IDF = 2.5;
Float* floatptr = &idf;
vacío* vd;
vd = floatptr;

El código se compila sin un mensaje de advertencia o error.

Funcionar a las conversiones de puntero

Un puntero a una función que no lanzaría una excepción puede asignarse a un puntero para funcionar. El siguiente código ilustra esto:

#incluir
usando el espacio de nombres STD;
nulo fn1 () noexcept

cout << "with noexcept" << '\n';

void fn2 ()

//declaraciones

void (*func1) () noexcept;
void (*func2) ();
int main ()

func1 = &fn1;
func2 = &fn2;
func2 = &fn1;
func2 ();
regresar 0;

La salida es con noexcept.

Conversiones booleanas

En C ++, las entidades que pueden dar como resultado falsas incluyen "cero", "puntero nulo" y "puntero de miembro nulo."Todas las demás entidades dan como resultado verdaderas. El siguiente código ilustra esto:

bool a = 0.0; cout << a <<'\n';
float* floatptr = 0;
bool b = floatptr; cout << b <<'\n';
bool c = -2.5; cout << c <<'\n';
bool d = +2.5; cout << d <<'\n';

La salida es:

0 // para falso
0 // para falso
1 // para verdadero
1 // para verdadero

Lvalue, pralupa y xvalue

Considere el siguiente código:

int id = 35;
int & id1 = id;
cout << id1 << '\n';

La salida es 35. En el código, ID e ID1 son Lvalues ​​porque identifican una ubicación (objeto) en la memoria. La salida 35 es un pralentero. Cualquier literal, excepto una cuerda literal, es un pralente. Otros praltos no son tan obvios, como en los ejemplos que siguen. Considere el siguiente código:

int id = 62;
int* ptr = &id;
int* pter;

PTR es un lvalue porque identifica una ubicación (objeto) en la memoria. Por otro lado, Pter no es un LValue. Pter es un puntero, pero no identifica ninguna ubicación en la memoria (no apunta a ningún objeto). Entonces, Pter es un pralente.

Considere el siguiente código:

nulo fn ()

//declaraciones

void (*func) () = &fn;
float (*functn) ();

Fn () y (*func) () son expresiones lvalue porque identifican una entidad (función) en la memoria. Por otro lado, (*Functn) () no es una expresión de Lvalue. (*functn) () es un puntero a una función, pero no identifica ninguna entidad en la memoria (no apunta a ninguna función en la memoria). Entonces, (*functn) () es una expresión de pralente.

Ahora, considere el siguiente código:

estructuras

int n;
;
S obj;

S es una clase y OBJ es un objeto instanciado de la clase. OBJ identifica un objeto en la memoria. Una clase es una unidad generalizada. Entonces, S realmente no identifica ningún objeto en la memoria. Se dice que S es un objeto no identificado. S también es una expresión de praltos.

El enfoque de este artículo está en los praltos. Pralentarse significa rValue puro.

Xvalor

Xvalue significa valor vencido. Los valores temporales están expirando valores. Un lvalue puede convertirse en un xvalue. Un pralentador también puede convertirse en un xvalue. El enfoque de este artículo está en los praltos. Un XValue es un LValue o una referencia de Rvalue sin nombre cuyo almacenamiento se puede reutilizar (generalmente porque está cerca del final de su vida). Considere el siguiente código que funciona:

estructuras

int n;
;
int q = s ().norte;

La expresión "int q = s ().norte;" copia el valor que n deige a Q. S () es solo un medio; no es una expresión de uso regular. S () es un pralentero cuyo uso lo ha convertido a un xvalue.

Conversiones de Lvalue-to-Ralue

Considere la siguiente declaración:

int ii = 70;

70 es un pralente (rValue) y II es un lvalue. Ahora, considere el siguiente código:

int ii = 70;
int tt = ii;

En la segunda declaración, II se encuentra en la situación de un pralente, por lo que II se convierte en un praleo allí. En otras palabras, el compilador convierte II en un praleo implícitamente. Es decir, cuando se usa un lvalue en una situación en la que la implementación espera un praleo, la implementación convierte el lvalue en un pralente.

Conversiones de matriz a punto

Considere el siguiente código que funciona:

char* p;
char q [] = 'a', 'b', 'c';
p = & q [0];
++pag;
cout<<*p<<'\n';

La salida es b. La primera declaración es una expresión y es un puntero a un personaje. Pero a qué personaje se está señalando la declaración? - Sin carácter. Entonces, es un pralente y no un LValue. La segunda declaración es una matriz en la que Q [] es una expresión de Lvalue. La tercera declaración convierte el pralente, p, en una expresión de Lvalue, que apunta al primer elemento de la matriz.

Conversiones de función al punto

Considere el siguiente programa:

#incluir
usando el espacio de nombres STD;
void (*func) ();
nulo fn ()

//declaraciones

int main ()

func = &fn;
regresar 0;

La expresión "nulo (*func) ();" es un puntero a una función. Pero a qué función está apuntando la expresión? - Sin función. Entonces, es un pralente y no un LValue. Fn () es una definición de función, donde FN es una expresión de Lvalue. En main (), "func = &fn;"Convierte el praleo, func, en una expresión de Lvalue que apunta a la función, fn ().

Conversiones de materialización temporal

En C ++, se puede convertir un pralente a un xvalue del mismo tipo. El siguiente código ilustra esto:

estructuras

int n;
;
int q = s ().norte;

Aquí, el praleo, s (), se ha convertido en un xvalue. Como xvalue, no duraría mucho; ver más explicación arriba.

Conversiones de calificación

Un tipo calificado por CV es un tipo calificado por la palabra reservada, "const" y/o la palabra reservada, "volátil."

La calificación CV también está clasificada. Ninguna calificación CV es menor que la calificación "const", que es menor que la calificación "const volátil". Ninguna calificación CV es menor que la calificación "volátil", que es menos que la calificación "const volátil". Entonces, hay dos corrientes de clasificación. Un tipo puede estar más calificado por CV que otro.

Se puede convertir un tipo de cV calificado por cV más bajo a un tipo de pralentamiento más calificado por CV. Ambos tipos deben ser Pointer-to-CV.

Conclusión

Las entidades C ++ se pueden convertir de un tipo a un tipo relacionado implícita o explícitamente. Sin embargo, el programador debe comprender lo que se puede convertir y lo que no se puede convertir, y en qué forma. La conversión puede tener lugar en los siguientes dominios: conversiones integrales, conversiones de punto flotante, conversiones de integral flotante, conversiones aritméticas habituales, conversiones de puntero, con conversiones de puntero, conversiones booleanas, conversiones de lvalue a-revalor , Conversiones de función a poner, conversiones de materialización temporales y conversiones de calificación.