Namespaces
Variants

Member access operators

From cppreference.net

Los operadores de acceso a miembros permiten acceder a los miembros de sus operandos.

Operador Nombre del operador Ejemplo Descripción
[ ] subíndice de array a [ b ] accede al elemento b del array a
* desreferencia de puntero * a desreferencia el puntero a para acceder al objeto o función al que hace referencia
& dirección de & a crea un puntero que referencia al objeto o función a
. acceso a miembro a. b accede al miembro b de la struct o union a
- > acceso a miembro a través de puntero a - > b accede al miembro b de la struct o union apuntada por a

Contenidos

Subíndice

La expresión de subíndice de array tiene la forma

pointer-expression [ integer-expression ] (1)
integer-expression [ pointer-expression ] (2)

donde

pointer-expression - una expresión de tipo puntero a objeto completo
integer-expression - una expresión de tipo entero

La expresión del operador de subíndice es una expresión lvalue cuyo tipo es el tipo del objeto apuntado por pointer-expression .

Por definición, el operador de subíndice E1 [ E2 ] es exactamente idéntico a * ( ( E1 ) + ( E2 ) ) . Si pointer-expression es una expresión de array, sufre lvalue-to-rvalue conversion y se convierte en un puntero al primer elemento del array.

Debido a la definición de la suma entre un puntero y un entero , el resultado es el elemento del array con el índice igual al resultado de integer-expression (o, si pointer-expression apuntaba al i-ésimo elemento de algún array, el índice del resultado es i más el resultado de integer-expression )

Nota: consulte array para los detalles sobre arreglos multidimensionales.

#include <stdio.h>
int main(void)
{
    int a[3] = {1,2,3};
    printf("%d %d\n", a[2],  // n == 3
                      2[a]); // same, n == 3
    a[2] = 7; // subscripts are lvalues
    int n[2][3] = {{1,2,3},{4,5,6}};
    int (*p)[3] = &n[1]; // elements of n are arrays
    printf("%d %d %d\n", (*p)[0], p[0][1], p[0][2]); // access n[1][] via p
    int x = n[1][2]; // applying [] again to the array n[1]
    printf("%d\n", x);
    printf("%c %c\n", "abc"[2], 2["abc"]); // string literals are arrays too
}

Salida:

3 3
4 5 6
6
c c

Desreferencia

La expresión de dereference o indirection tiene la forma

* expresión-de-puntero

donde

pointer-expression - una expresión de cualquier tipo de puntero

Si pointer-expression es un puntero a función, el resultado del operador de desreferencia es un designador de función para esa función.

Si pointer-expression es un puntero a objeto, el resultado es una expresión lvalue que designa el objeto apuntado.

Desreferenciar un puntero nulo, un puntero a un objeto fuera de su tiempo de vida (un puntero colgante), un puntero desalineado o un puntero con valor indeterminado es comportamiento indefinido, excepto cuando el operador de desreferencia se anula aplicando el operador de dirección a su resultado, como en & * E .

#include <stdio.h>
int main(void)
{
    int n = 1;
    int* p = &n;
    printf("*p = %d\n", *p); // el valor de *p es lo almacenado en n
    *p = 7; // *p es lvalue
    printf("*p = %d\n", *p);
}

Salida:

*p = 1
*p = 7

Dirección de

La expresión de dirección tiene la forma

& función (1)
& expresión-lvalue (2)
& * expresión (3)
& expresión [ expresión ] (4)
1) dirección de una función
2) dirección de un objeto
3) caso especial: & y * se cancelan mutuamente, ninguno se evalúa
4) caso especial: & y el * que está implícito en [] se cancelan mutuamente, solo la adición implícita en [] es evaluada.

donde

lvalue-expression - una expresión lvalue de cualquier tipo que no sea un campo de bits y no tenga clase de almacenamiento register

El operador de dirección produce la dirección no lvalue de su operando, adecuada para inicializar un puntero al tipo del operando. Si el operando es un designador de función (1) , el resultado es un puntero a función. Si el operando es un objeto (2) , el resultado es un puntero a objeto.

Si el operando es el operador de desreferencia, no se realiza ninguna acción (por lo que es válido aplicar &* a un puntero nulo), excepto que el resultado no es un lvalue.

Si el operando es una expresión de índice de array, no se realiza ninguna acción aparte de la conversión de array-a-puntero y la adición, por lo que &a[N] es válido para un array de tamaño N (obtener un puntero un elemento más allá del final es válido, desreferenciarlo no lo es, pero la desreferencia se cancela en esta expresión).

int f(char c) { return c;}
int main(void)
{
   int n = 1;
   int *p = &n; // dirección del objeto n
   int (*fp)(char) = &f; // dirección de la función f
   int a[3] = {1,2,3};
   int *beg=a, *end=&a[3]; // mismo que end = a+3
}

Acceso a miembros

La expresión de acceso a miembro tiene la forma

expresión . nombre-miembro

donde

expression - una expresión de tipo struct o union
member-name - un identificador que nombra un miembro de la struct o union designada por expression

La expresión de acceso a miembro designa el miembro nombrado de la struct o union designado por su operando izquierdo. Tiene la misma categoría de valor que su operando izquierdo.

Si el operando izquierdo está calificado como const o volatile , el resultado también está calificado. Si el operando izquierdo es atomic , el comportamiento es indefinido.

Nota: además de los identificadores que nombran objetos de tipo struct o union, las siguientes expresiones pueden tener tipos struct o union: assignment , function call , comma operator , conditional operator , y compound literal .

#include <stdio.h>
struct s {int x;};
struct s f(void) { return (struct s){1}; }
int main(void)
{
    struct s s;
    s.x = 1; // ok, cambia el miembro de s
    int n = f().x; // f() es una expresión de tipo struct s
//  f().x = 1; // Error: esta expresión de acceso a miembro no es un lvalue
    const struct s sc;
//  sc.x = 3;  // Error: sc.x es const, no puede ser asignado
    union { int x; double d; } u = {1};
    u.d = 0.1; // cambia el miembro activo de la unión
}

Acceso a miembros a través de puntero

La expresión de acceso a miembro tiene la forma

expresión -> nombre-de-miembro

donde

expression - una expresión de tipo pointer a struct o union
member-name - un identifier que nombra un miembro del struct o union apuntado por expression

La expresión de acceso a miembro a través de puntero designa el miembro nombrado de la struct o union apuntada por su operando izquierdo. Su categoría de valor es siempre lvalue

Si el tipo apuntado por el operando izquierdo está calificado como const o volatile , el resultado también está calificado. Si el tipo apuntado por el operando izquierdo es atomic , el comportamiento no está definido.

#include <stdio.h>
struct s {int x;};
int main(void)
{
    struct s s={1}, *p = &s;
    p->x = 7; // cambia el valor de s.x a través del puntero
    printf("%d\n", p->x); // imprime 7
}

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
DR 076 C89 la indirección innecesaria no podía cancelarse con & hecho cancelable

Referencias

  • Estándar C17 (ISO/IEC 9899:2018):
  • 6.5.2.1 Indexación de arreglos (p: 57-58)
  • 6.5.2.3 Miembros de estructuras y uniones (p: 58-59)
  • 6.5.3.2 Operadores de dirección e indirección (p: 59-61)
  • Estándar C11 (ISO/IEC 9899:2011):
  • 6.5.2.1 Indexación de arreglos (p: 80)
  • 6.5.2.3 Miembros de estructuras y uniones (p: 82-84)
  • 6.5.3.2 Operadores de dirección e indirección (p: 88-89)
  • Estándar C99 (ISO/IEC 9899:1999):
  • 6.5.2.1 Array subscripting (p: 70)
  • 6.5.2.3 Structure and union members (p: 72-74)
  • 6.5.3.2 Address and indirection operators (p: 78-79)
  • Estándar C89/C90 (ISO/IEC 9899:1990):
  • 3.3.2.1 Subíndices de array
  • 3.3.2.3 Miembros de estructura y unión
  • 3.3.3.2 Operadores de dirección e indirección

Véase también

Operadores comunes
asignación incremento
decremento
aritméticos lógicos comparación acceso a
miembros
otros

a = b
a + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b

a [ b ]
* a
& a
a - > b
a. b

a ( ... )
a, b
( type ) a
a ? b : c
sizeof


_Alignof
(desde C11)
(hasta C23)

alignof
(desde C23)

Documentación de C++ para Operadores de acceso a miembros