Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.9.2  Operadores de asignación

§1  Sinopsis

C++ dispone de los siguientes operadores de asingación:

=            Asignación

*=           Asigna producto

/=           Asigna división

%=          Asigna resto (módulo)

+=           Asigna suma

-=            Asigna diferencia (resta)

<<=         Asigna desplazamiento izquierda

>>=         Asigna desplazamiento derecha

&=           Asigna AND entre bits

^=           Asigna XOR  entre bits

|=            Asigna OR  entre bits

§2  Sintaxis:

      <expr-unaria> <operador-de-asignación> <expr-derecha>

Ejemplo:

x = 3;
x += 3;
x &= 3;

§3  Comentario

Todos ellos son operadores binarios, de los cuales,  = es el único de asignación simple, los demás son operadores de asignación compuestos.

Los seis primeros aceptan operandos de distinto tipo, mientras que los cinco últimos: <<=, >>=, &=, ^= y |=, implican manejo de bits ( 4.9.3), por lo que sus operandos deben ser tipos int en sus distintas variantes.


§3.1  No olvidar que las expresiones de asignación producen un resultado. El tipo resultante es el de la <expr-unaria> (izquierda); el valor que se aplica es el determinado por <expr-derecha> (el Rvalue 2.1.5). El valor resultante de <expr-unaria> después de la asignación, es el resultado de la expresión (el Lvalue 2.1.5). Así pues, cualquiera que sea su sentido concreto, todos implican la "copia" de un bloque de memoria (que contiene el "resultado") en algún sitio (la dirección indicada por el Rvalue).

Ejemplo:

int num;  float f = 3.14;
num = f + 1;

En este caso, el valor 4.14, resultado de <expr-derecha>, se aplica a num. Teniendo en cuenta que el tipo resultante debe ser el de num (un int en este caso), se realiza automáticamente una conversión del float 4.14 a int (con pérdida de precisión si es necesario), con el resultado de que num recibe el valor 4 y el resultado de la asignación es un int de valor 4.


§3.2  Esta propiedad de las asignaciones de producir un resultado, es justamente la que permite expresiones de asignación compuesta del tipo:

A = B = C = D;

y es ampliamente utilizada en la programación de C++. Considere el bucle del siguiente ejemplo:

while ( (ch = getchar() ) != 27 ) ;

aprovechando que en este caso, el resultado de la asignación es un char, se utiliza directamente en la cláusula del while, resultando que el bucle se ejecuta indefinidamente hasta que se pulse la tecla ESC (escape).


§3.3  En general las sentencias de asignación tienen la forma:

variable = expresion

La parte izquierda (que tiene que ser un Lvalue no constante) adquiere el valor señalado en la expresión de la derecha, pero se mantiene el tipo original de la variable de la parte izquierda. En caso necesario se realiza una conversión de tipo (con pérdida de precisión en su caso) del izquierdo al derecho.

Nota: observe que el operador C++ de asignación simple (=) se distingue de otros lenguajes como Pascal que utilizan el símbolo := para este operador. Observe también que la asignación simple (=) utiliza un símbolo distinto del operador relacional de igualdad (==).


§4   Las variables se pueden inicializar en el mismo momento de la declaración (asignándoles un valor). Este es el único caso en que se puede asignar una constante [2]. Ejemplo:

int primero =  0;
char ch = ‘a’;
float balance = 123.456;
char string[10] = "1234567890";
const float pi = 3.14159 ;


§5  En la expresión E1 = E2E1 debe ser un Lvalue modificable, en caso contrario puede obtenerse un mensaje de error: Lvalue required [1]. Por ejemplo, una vez declarado char a[10], ninguna de las dos sentencias que siguen es válida:

a = "0123456789";
a[10] = "0123456789";

La expresión de asignación en sí misma no es un Lvalue.


§6  Si @ es un operador compuesto, la expresión E1 @= E2 equivale a E1 = E1 @ E2. Por ejemplo: E1 += E2 equivale a E1 = E1 + E2.

Ejemplos

x *= y       /* equivalentes */   x = x * y
x *= y + 2   /* equivalentes */   x = x * (y + 2)

Ejemplo operativo:

#include <iostream>
using namespace std;

int main() {      // ===============
   int sec = 3628;
   cout << sec << " segundos son ";
   int h = sec / (60*60);
   cout << h << " hora y ";
   sec %= 60*60;
   int m = sec / 60;
   cout << m << " minutos y ";
   sec %= 60;
   cout << sec << " segundos" << endl;
}

Salida:

3628 segundos son 1 hora y 0 minutos y 28 segundos


§7  Tanto para las asignaciones simples como compuestas, ambos operandos E1 y E2 deben cumplir alguna de las siguientes condiciones (asumimos que E1 está a la izquierda del operador y E2 es el de la derecha):

  • E1 es de tipo aritmético, cualificado o no y E2 es un tipo aritmético.

  • E1 es una estructura o unión cualificada o no, pero de tipo compatible con E2.

  • E1 y E2 son punteros a versiones no cualificadas de tipos compatibles, el tipo de objeto señalado por E1 tiene todos los calificadores del tipo de objeto señalado por E2.

  • E1 o E2 es un puntero a objeto o tipo incompleto, y el otro es un puntero a una versión cualificada o no cualificada de void. El tipo de objeto señalado por E1 tiene todos los calificadores del objeto señalado por E2.

  • E1 es un puntero y E2 es un puntero nulo.

  • No puede haber espacios entre los operadores compuestos (+  =)

  • Hay ciertas condiciones, en que los operadores de asignación no pueden aplicarse cuando se trata de propiedades de clases (4.9.2a).

Ejemplos

char* = 0;    // asignación de nulo a puntero a carácter
char *= 0;    // char = char * 0

  Precauciónes !!

Es relativamente frecuente confundir el orden de escritura de estos operadores. Recuerde que, en todos los casos de asignación compuesta, el símbolo "=" va a la derecha!!.

Considere el siguiente ejemplo:

#include <iostream.h>

void main() {                   // ==============
  int x = 2, y = 4;
  int* z = &x;
  x =& y;                        // Error !!

  x &= y;                        // Ok.
  z =& y;                        // Ok.   Asignar un puntero!!
  cout << "x = " << x << endl;  // Comprobaciones.
  cout << "y = " << y << endl;
  cout << "z = " << z << endl;
}

Salida (después de eliminada la sentencia errónea):

x = 0
y = 4
z = 0065FDFC

  Inicio.


[1]  Es importante recordar este extremo cuando se sobrecarga el operador de asignación para miembros de clases ( 4.9.18a).

[2]  Las constantes que son miembros de clases (propiedades) tienen un procedimiento especial de inicialción, ya que la regla de no poder modificar su valor después de la declaración colisiona con otra regla de la declaración de clases: No permitir inicializaciones de los miembros en el cuerpo de la declaración ( 4.11.2d3).