Member access operators
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 .
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) | ||||||||
&
y
*
se cancelan mutuamente, ninguno se evalúa
&
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
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
Documentación de C++
para
Operadores de acceso a miembros
|