C ++

Conversiones estándar de C ++

Conversiones estándar de C ++
Hay dos tipos de entidad en C ++, los tipos fundamentales y los tipos compuestos. Los tipos fundamentales son los tipos escalares. Los tipos 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:

#incluir
#incluir
usando el espacio de nombres std;
int main ()

int rt1 = sqrt (5);
int rt2 = raíz cuadrada (8);
cout<return 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 derribado las respuestas de la raíz cuadrada de 5 y la raíz cuadrada de 8. Este artículo no analiza el piso o el 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 hecha, 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 integrales flotantes
  • Clasificación de conversión de enteros
  • Promociones integrales
  • Conversiones aritméticas habituales
  • Promoción de punto flotante
  • Conversiones de puntero
  • Conversiones de función a puntero
  • Conversiones booleanas
  • Lvalue, prvalue y xvalue
  • Xvalue
  • Conversiones de lvalor a rvalue
  • Conversiones de matriz a puntero
  • Conversiones de función a puntero
  • Conversiones de materialización temporal
  • Conversiones de calificación
  • Conclusión

Conversiones integrales

Las conversiones integrales son conversiones enteras. Los enteros sin signo incluyen "unsigned char", "unsigned short int", "unsigned int", "unsigned long int" y "unsigned long long int."Los enteros con signo correspondientes incluyen" caracteres con signo "," int corto "," int "," int largo "y" int largo largo."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 en un tipo correspondiente sin ningún problema. El problema ocurre cuando se convierte de un tipo de rango más grande a un tipo de rango más pequeño, o al convertir un número con signo en un número sin signo correspondiente.

Cada compilador tiene un valor máximo que puede tomar para el int corto. Si se asigna un número mayor que ese máximo, destinado a un int, al int corto, el compilador seguirá algún algoritmo y devolverá un número dentro del rango del int corto. Si el programador tiene suerte, el compilador advertirá sobre 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 límite para cada tipo de entidad.

Si un número int corto con signo negativo se va a convertir en un número int corto sin signo, el compilador seguirá algún algoritmo y devolverá un número positivo dentro del rango del int corto sin signo. 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 booleano verdadero. 0 se convierte en booleano falso. El siguiente código ilustra esto:

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

1 de verdad
1 de verdad
0 para falso

Conversiones de punto flotante

Los tipos de coma flotante incluyen "float", "double" y "long double."Los tipos de coma flotante no se agrupan en firmados y sin firmar, como enteros. Cada tipo puede tener un número firmado o no firmado. Un tipo de punto flotante debe tener al menos la misma precisión que su predecesor. Es decir, "long double" debe tener una precisión igual o mayor a "double" y "double" debe tener una precisión igual o mayor a "float."

Recuerde que el rango de un tipo de coma flotante no es continuo; más bien, es en pequeños pasos. Cuanto mayor sea la precisión del tipo, menores serán 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 menor precisión a un tipo de mayor precisión, el programador debe aceptar un falso aumento 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 mayor precisión a un tipo de menor precisión, el programador debe aceptar una pérdida de precisión. Si se debe reducir el número de bytes para el almacenamiento de números, 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 integrales flotantes

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

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

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

Clasificación de conversión de enteros

Cualquier tipo de entero tiene un rango que se le ha dado. Esta clasificación ayuda a la conversión. La clasificación es relativa; los rangos no están en niveles fijos. Excepto por char y char con signo, no hay dos enteros con signo que tengan el mismo rango (asumiendo que char está firmado). Los tipos de enteros sin signo tienen la misma clasificación que sus correspondientes tipos de enteros con signo. La clasificación es la siguiente:

  • Suponiendo que char está firmado, entonces char y char firmado tienen el mismo rango.
  • El rango de un tipo de entero con signo es mayor que el rango de un tipo de entero con signo de un número menor de bytes de almacenamiento. Entonces, el rango de int long long con signo es mayor que el rango de int long con signo, que es mayor que el rango de int con signo, que es mayor que el rango de int corto con signo, que es mayor que el rango de char con signo.
  • El rango de cualquier tipo de entero sin signo es igual al rango del tipo de entero con signo correspondiente.
  • El rango de carácter sin firmar es igual al rango de carácter firmado.
  • bool tiene el menor rango; su rango es menor que el de los caracteres firmados.
  • char16_t tiene el mismo rango que el int corto. char32_t tiene el mismo rango que el int. Para el compilador de g ++, wchar_t tiene el mismo rango que el int.

Promociones integrales

Promociones integrales son promociones enteras. No hay ninguna razón por la que un número entero de menos bytes no pueda ser representado por un número entero de bytes mayores. Integer Promotions se ocupa de todo lo siguiente:

  • Un int corto firmado (dos bytes) se puede convertir en un int firmado (cuatro bytes). Un int corto sin firmar (dos bytes) se puede convertir en un int sin firmar (cuatro bytes). Nota: convertir un int corto en un int largo o un int largo y largo 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 la misma cantidad de bytes).
  • Con el compilador g ++, un tipo char16_t se puede convertir en un tipo int firmado o un tipo int sin firmar; un tipo char32_t se puede convertir en un tipo int firmado o un tipo int sin firmar; y un tipo wchar_t se puede convertir en un tipo int firmado o sin firmar.
  • Un tipo bool se puede convertir en un tipo int. En este caso, verdadero se convierte en 1 (cuatro bytes) y falso se convierte en 0 (cuatro bytes). El int puede estar firmado o firmado.
  • La promoción de enteros también existe para el tipo de enumeración sin ámbito; ver más adelante.

Conversiones aritméticas habituales

Considere el siguiente código:

flotar f = 2.5;
int i = f;
cout<El código se compila sin indicar ninguna advertencia o error, dando el resultado de 2, que probablemente no es 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;
flotador 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 conocer para evitar errores en la codificación. Las conversiones aritméticas habituales en operadores binarios son las siguientes:

  • Si alguno de los operandos es del tipo "doble largo", el otro se convertirá en doble largo.
  • De lo contrario, si alguno de los operandos es doble, el otro se convertirá en doble.
  • De lo contrario, si alguno de los operandos es flotante, el otro se convertirá en flotante. En el código anterior, el resultado de i1 / i2 es oficialmente 2; es por eso que flt es 2. El resultado del binario, /, se aplica como el operando derecho al operador binario, =. Entonces, el valor final de 2 es un flotante (no un int).

DE LO CONTRARIO, UNA PROMOCIÓN INTEGRADA TENDRÍA LUGAR COMO SIGUE:

  • Si ambos operandos son del mismo tipo, no se realizan más conversiones.
  • De lo contrario, si ambos operandos son tipos enteros con signo o ambos son tipos enteros sin signo, entonces el operando del tipo con el rango entero más bajo se convertirá al tipo de operando con el rango más alto.
  • De lo contrario, si un operando tiene signo y el otro no tiene signo, y si el tipo de operando sin signo es mayor o igual al rango del tipo de operando con signo, y si el valor del operando con signo es mayor o igual a cero, el operando firmado se convertirá al tipo de operando sin firmar (teniendo en cuenta el rango). Si el operando con signo es negativo, 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 de entero con signo y el otro es un tipo de entero sin signo, y si todos los valores posibles del tipo del operando con el tipo de entero sin signo pueden ser representados por el tipo de entero con signo, entonces el tipo de entero sin signo se ser convertido al tipo de operando del tipo entero con signo.
  • De lo contrario, los dos operandos (un char y un bool, por ejemplo) se convertirían al tipo entero sin signo.

Promoción de punto flotante

Los tipos de coma flotante 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 flotante a doble o de doble a doble larga.

Conversiones de puntero

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

int id = 6;
int * intPtr = &id;
flotador idf = 2.5;
float * floatPtr = &idf;
intPtr = floatPtr; // error aquí

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

int id = 6;
int * intPtr = &id;
intPtr = 0;
flotador idf = 2.5;
float * floatPtr = &idf;
floatPtr = 0;
intPtr = floatPtr; // error aquí

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

int id = 6;
int * intPtr = &id;
int * const intPC = 0;
flotador idf = 2.5;
float * floatPtr = &idf;
float * const floatPC = 0;
intPC = floatPC; // error aquí

A un puntero nulo se le puede dar un valor de dirección diferente para su tipo. El siguiente código ilustra esto:

flotador idf = 2.5;
float * floatPtr = 0;
floatPtr = &idf;
cout<<*floatPtr<<'\n';

La salida es 2.5.

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

flotador idf = 2.5;
float * const floatPC = 0;
floatPC = &idf; // error aquí

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

flotador idf = 2.5;
float * const floatPC = 0;
float * floatPter = &idf;
floatPter = floatPC; //OK
cout << floatPter << '\n';

La salida es 0.

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

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

flotador idf = 2.5;
float * floatPtr = &idf;
void * vd;
vd = floatPtr;

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

Conversiones de función a puntero

Un puntero a una función que no arrojaría una excepción se puede asignar a un puntero a la función. El siguiente código ilustra esto:

#incluir
usando el espacio de nombres std;
void fn1 () no excepto

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

vacío fn2 ()

//declaraciones

void (* func1) () no excepto;
void (* func2) ();
int main ()

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

La salida es sin excepción.

Conversiones booleanas

En C ++, las entidades que pueden resultar en falso incluyen "cero", "puntero nulo" y "puntero de miembro nulo."Todas las demás entidades dan como resultado. 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 // de verdad
1 // de verdad

Lvalue, prvalue 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 valores l porque identifican una ubicación (objeto) en la memoria. La salida 35 es un valor pr. Cualquier literal, excepto un literal de cadena, es un valor pr. Otros valores pr 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 lvalor. Pter es un puntero, pero no identifica ninguna ubicación en la memoria (no apunta a ningún objeto). Entonces, pter es un valor.

Considere el siguiente código:

vacío fn ()

//declaraciones

void (* func) () = &fn;
flotar (* función) ();

Fn () y (* func) () son expresiones de valor l porque identifican una entidad (función) en la memoria. Por otro lado, (* functn) () no es una expresión 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 prvalue.

Ahora, considere el siguiente código:

estructura S

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 sin nombre. S también es una expresión de valor.

El enfoque de este artículo está en los valores. Prvalue significa puro rvalue.

Xvalue

Xvalue son las siglas de Expiring Value. Los valores temporales son valores que expiran. Un valor l puede convertirse en un valor x. Un prvalue también puede convertirse en un xvalue. El enfoque de este artículo está en los valores. 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 útil). Considere el siguiente código que funciona:

estructura S

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

La expresión "int q = S ().norte;" copia cualquier valor que n tenga en q. S () es solo un medio; no es una expresión de uso habitual. S () es un prvalue cuyo uso lo ha convertido en un xvalue.

Conversiones de lvalor a rvalue

Considere la siguiente declaración:

int ii = 70;

70 es un prvalue (rvalue) y ii es un lvalue. Ahora, considere el siguiente código:

int ii = 70;
int tt = ii;

En el segundo enunciado, ii está en la situación de un prvalue, por lo que ii se convierte en un prvalue allí. En otras palabras, el compilador convierte ii en un prvalue implícitamente. Es decir, cuando se usa un lvalue en una situación en la que la implementación espera un prvalue, la implementación convierte el lvalue en un prvalue.

Conversiones de matriz a puntero

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 carácter. Pero, ¿a qué personaje apunta la declaración?? - Sin personaje. Entonces, es un prvalue 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 prvalue, p, en una expresión lvalue, que apunta al primer elemento de la matriz.

Conversiones de función a puntero

Considere el siguiente programa:

#incluir
usando el espacio de nombres std;
void (* func) ();
vacío fn ()

//declaraciones

int main ()

func = &fn;
return 0;

La expresión "void (* func) ();" es un puntero a una función. Pero, ¿a qué función apunta la expresión? - Sin función. Entonces, es un prvalue y no un lvalue. Fn () es una definición de función, donde fn es una expresión de valor l. En main (), "func = &fn;”Convierte el prvalue, func, en una expresión lvalue que apunta a la función, fn ().

Conversiones de materialización temporal

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

estructura S

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

Aquí, el prvalue, S (), se ha convertido en un xvalue. Como valor x, no duraría mucho; vea más explicación arriba.

Conversiones de calificación

Un tipo calificado de cv es un tipo calificado por la palabra reservada, "const", y / o la palabra reservada, "volatile."

La calificación CV también se clasifica. Ninguna calificación de cv es menor que la calificación "const", que es menor que la calificación "const volatile". Ninguna calificación cv es menor que la calificación "volátil", que es menor que la calificación "constante volátil". Entonces, hay dos corrientes de clasificación de calificación. Un tipo puede estar más calificado de cv que otro.

Un tipo calificado de cv de prvalue más bajo se puede convertir en un tipo de prvalue más calificado de cv. Ambos tipos deben ser de puntero a CV.

Conclusión

Las entidades de C ++ se pueden convertir de un tipo a un tipo relacionado implícita o explícitamente. Sin embargo, el programador debe comprender qué se puede convertir y qué no, y en qué forma. La conversión puede tener lugar en los siguientes dominios: conversiones integrales, conversiones de coma flotante, conversiones integrales flotantes, conversiones aritméticas habituales, conversiones de puntero, conversiones de función a puntero, conversiones booleanas, conversiones de valor L a valor r, conversiones de matriz a puntero , Conversiones de función a puntero, conversiones de materialización temporal y conversiones de calificación.

Agregue gestos del mouse a Windows 10 con estas herramientas gratuitas
En los últimos años, las computadoras y los sistemas operativos han evolucionado enormemente. Hubo un momento en que los usuarios tenían que usar coma...
Controle y administre el movimiento del mouse entre múltiples monitores en Windows 10
Administrador de mouse de doble pantalla le permite controlar y configurar el movimiento del mouse entre varios monitores, al ralentizar sus movimient...
WinMouse le permite personalizar y mejorar el movimiento del puntero del mouse en una PC con Windows
Si desea mejorar las funciones predeterminadas del puntero del mouse, use el software gratuito WinMouse. Agrega más funciones para ayudarlo a aprovech...