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.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).