Disponible la versión 6 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.1  Operadores aritméticos

§1  Sinopsis

Los operadores aritméticos se usan para realizar cálculos de aritmética de números reales y de aritmética de punteros. C++ dispone de los siguientes:

+       Dos posibilidades:   Suma binaria más unitario .

++     Incremento unitario (dos clases )

-        Dos posibilidades: Resta binaria menos unitario .

--       Decremento unitario (dos clases )

*        Multiplicación (este símbolo tiene también otros usos )

/        División  .

%      Resto o módulo  .

Nota: la aritmética de números reales es la clásica de la escuela primaria. La de punteros es una aritmética un tanto especial y rudimentaria ( 4.2.2).

§2  Observaciones

Los operadores aritméticos pertenecen a dos grupos: unos aceptan operandos de tipo numérico; otros aceptan operandos de tipo puntero-a-tipoX [3]. Además son de dos tipos; unarios (que aceptan un solo operando) y binarios (que aceptan dos). La clasificación es la siguiente:

Operadores aritméticos unarios:

+       más unitario.

++     Incremento unitario (dos clases)

-        menos unitario.

--       Decremento unitario (dos clases)

Operadores artiméticos binaros:

+       Suma binaria.

-        Resta binaria.

*        Multiplicación

/        División.

%      Resto o módulo.

Estos últimos pueden combinarse con el de asignación = para dar origen a operadores compuestos ( 4.9.2) son los siguientes:

+=       Asigna suma

-=        Asigna diferencia (resta)

*=        Asigna producto

/=        Asigna división

%=       Asigna resto (módulo)


Tenga en cuenta que existen distintos operadores enmascarados bajo los mismos símbolos + y -. Es un caso de sobrecarga incluida en el propio lenguaje [1]. Como en el resto de los casos de sobrecarga, el compilador deduce por el contexto de que versión del operador se trata. Como veremos inmediatamente, en C++ es perfectamente válida una expresión del tipo:

int x = *ptr+-*++ptr;

En el ejemplo siguiente se muestran los casos posibles:

int ai[] = {2, 3};
int* ptr = ai;
int r1 = +ai[0];          // L.3: más unitario sobre tipo numérico
int r2 = -ai[1]           // L.3: menos unitario sobre tipo numérico
int r3 = ai[0] + ai[1];   // L.4: 2 + 3 suma binaria (de enteros)
int r4 = ai[1] - ai[0]    // L.5: 3 - 2 resta binaria (de enteros)
int r5 = ai[0] + -ai[1];  // L.6: 2 +(-3) suma binaria seguida de menos unitario
int r6 = *ptr + -*++ptr;  // L.7: Suma binaria (de enteros) a + (-b)


En L.7 coexisten tres operadores aritméticos no homogéneos (de izquierda a derecha):

+     Suma binaria entre valores numéricos tipo int (). Los valores *ptr y -*++ptr

-      Negación unitaria de un valor numérico tipo int (); el valor *(++ptr)

++   Preincremento de un puntero-a-int  ( ). Equivale a suma binaria de puntero y entero: ++ptr == ptr = ptr + 1

Nota: aunque válida, la sentencia de L.7 es un ejemplo de expresión peligrosa y desaconsejada. En 4.9.0a se ha presentado una explicación del sorpresivo resultado ( 0 ) que se obtiene para L.6.

§3  Suma y resta binaria

En el primer caso: suma y resta binaria, caben dos posibilidades sintácticas:

a-  expresión-suma + expresión-de-multiplicación

b-  expresión-suma - expresión-de-multiplicación

§3.1  Operador Suma binaria

Las posibilidades para los operandos en la expresión A + B son los siguientes:

  1. A y B son tipos aritméticos, enteros o fraccionarios ( 2.2.1). En este caso ambos operandos están sujetos a las posibles conversiones aritméticas estándar ( 2.2.5) y el resultado es la suma aritmética de ambos. Ejemplo:

    int x = 10,  y = 20;
    int z = x + y;         // z == 30

  2. A es un entero y B es un puntero a objeto. Ejemplo:

    int arr[5] = {1, 2, 3, 4, 5};
    int* ptr = &arr[0];     // Señala a 1
    int x = *(2 + ptr);     // x == 3

  3. A es un puntero a objeto y B es un entero. En estos dos últimos casos se aplican las reglas de aritmética de punteros ( 4.2.2). Ejemplo:

    int z = *(ptr + 3);     // x == 4

§3.2  Operador  Resta binaria.

Las posibilidades para los operandos en la expresión A - B son los siguientes:

  1. A y B son de tipo aritmético, entero o fraccionario; las posibilidades son las mismas que en el caso 1 de la suma binaria expuesta anteriormente. El resultado es la resta aritmética de ambos operandos. Ejemplo:

    int x = 10,  y = 20;
    int z = x - y;         // z == -10

  2. A y B son punteros a objetos de tipos compatibles. Ejemplo:

    int arr[5] = {1, 2, 3, 4, 5};
    int* pt1 = &arr[0];     // Señala a 1
    int* pt2 = &arr[4];     // Señala a 5
    int x = pt2 - pt1;      // x == 4

  3. A es un puntero a objeto y B es un entero. En estos dos últimos casos se aplican las reglas de aritmética de punteros ( 4.2.2). Ejemplo:

    int arr[5] = {1, 2, 3, 4, 5};
    int* ptr = &arr[4];     // señala a 5
    int x = *(ptr - 2);     // x == 3

§4  Operadores  ± Unitarios

Cuando los operadores + y - se utilizan como operadores unitarios, las posibilidades sintácticas son:

+ <expresión-cast>
- <expresión-cast>

En ambos casos <expresión-cast> debe ser de tipo numérico. Los resultados son respectivamente:

  • Valor del operando expresión-cast después de cualquier promoción interna que sea necesaria.

  • Valor negativo del operando expresión-cast después de cualquier promoción interna que se necesite.

Nota: recuerde que cuando + y - se utilizan como operadores unitarios, tienen mayor precedencia que cuando se utilizan como suma y resta binarias ( 4.9.0a).

Ejemplo

int x = 7, y = 3;
int r1 = - (y - x);     // r1 == 4
int r2 = + (y - x);     // r2 == -4
int r3 = - (x - y);     // r3 == -4
int r4 = + (x - y);     // r4 == 4

§5  Operadores  multiplicación y división

Los operadores binarios * (multiplicación) y / (división) realizan sus operaciones aritméticas correspondientes con todos los tipos numéricos (enteros y fraccionarios).

Sintaxis

expresión-de-multiplicación * expresión-cast
expresión-de-multiplicación / expresión-cast

§6  Operador módulo

El operador binario % (operador de módulo) devuelve el resto de la división de dos enteros, no puede ser utilizado con números fraccionarios float o double [2].

Sintaxis

expresión-de-multiplicación % expresión-cast

Ejemplo

int resto = (6 % 4);
cout << "El resto de 6/4 es " << resto << endl;

Salida:

El resto de 6/4 es 2

§7  Operadores  incremento y decremento

Los operadores unitarios ++ (incremento) y -- (decremento), suman y restan respectivamente una unidad al valor de la expresión. Existen dos variedades "Pre" y "Post" para cada uno de ellos.

Las posibilidades sintácticas son:

postfix-expression ++       (postincremento)
++ expresión-unitaria       (preincremento)
postfix-expression --       (postdecremento)
-- expresión-unitaria       (predecremento)

En los ejemplos que siguen suponemos que originariamente n == 5.

El postincremento añade uno a la expresión después de que se ha evaluado:

x = n++ ;     // -> x == 5  y  n == 6 

El preincremento añade uno antes de que sea evaluada la expresión.

x = ++n ;     // -> x == 6  y  n == 6

El postdecremento resta uno del valor de la expresión después de que sea evaluada.

x = n-- ;     // -> x == 5  y  n == 4

El predecremento resta uno antes de la evaluación de la expresión.

x = --n ;     // -> x == 4  y  n == 4

En ambos casos, el operando debe ser una variable, no una expresión. Por ejemplo: (x+y)++ es ilegal.


§7.1  Para evidenciar la diferencia entre preincremento y postincremento, observe las salidas que se obtienen con este pequeño programa según se van ejecutando las diversas líneas. Para interpretarlas correctamente debe tener en cuenta la precedencia de los operadores y recordar que, en todos los casos, el argumento recibido por printf es un puntero-a-carácter (char*). También deben recordarse las reglas de ámbito de los argumentos pasados a funciones.

char * s = "Hola mundo";
printf("Letra: \"%c\"\n", *s);      // Letra "H"
printf("Letra: \"%c\"\n", *s+1);    // Letra "I"
printf("Letra: \"%c\"\n", *(s+1));  // Letra "o"
printf("Letra: \"%c\"\n", *s++);    // Letra "H"
printf("Letra: \"%c\"\n", *s);      // Letra "o"
printf("Letra: \"%c\"\n", *++s);    // Letra "l"
printf("Letra: \"%c\"\n", *s);      // Letra "l"

Ver otros ejemplos en §4.10.3: ( Ejemplo-1); ( Ejemplo-2)

  Tema relacionado
  • Sobrecarga de los operadores aritméticos ( 4.9.18b2)

  Inicio.


[1]  Sin embargo, el lenguaje C++ no permite que las sobrecargas definidas por el usuario alteren el número de los operandos admitidos por un operador ( 4.9.18).

[2]  Para módulo entre números fraccionarios ver las funciones de Librería Estándar fmod y fmodl.

[3] Desde la óptica de C++, el tipo puntero-a-tipoX no es numérico; es distinto de int, float, double, Etc. Otra cosa es que se hayan definido operadores para realizar determinadas operaciones (aritméticas) sobre ellos, y que se realice una conversión automática o explícita de tipo ( 4.9.9d) en los casos en que se utilizan en conjunción con tipos enteros. Además de los operadores "aritméticos" aquí señalados, los punteros C++ disponen de operadores específicos ( 4.9.11).