Member access operators
멤버 접근 연산자는 피연산자의 멤버에 접근할 수 있도록 합니다.
| 연산자 | 연산자 이름 | 예시 | 설명 |
|---|---|---|---|
| [ ] | 배열 첨자 | a [ b ] | 배열 a 의 b 번째 요소에 접근 |
| * | 포인터 역참조 | * a | 포인터 a 를 역참조하여 해당 객체나 함수에 접근 |
| & | 주소 연산자 | & a | 객체나 함수 a 를 참조하는 포인터 생성 |
| . | 멤버 접근 | a. b | 구조체 또는 공용체 a 의 멤버 b 에 접근 |
| - > | 포인터를 통한 멤버 접근 | a - > b | a 가 가리키는 구조체 또는 공용체 의 멤버 b 에 접근 |
목차 |
첨자
배열 첨자 표현식의 형식은 다음과 같습니다
pointer-expression
[
integer-expression
]
|
(1) | ||||||||
integer-expression
[
pointer-expression
]
|
(2) | ||||||||
여기서
| pointer-expression | - | 완전 객체에 대한 포인터 타입의 표현식 |
| integer-expression | - | 정수 타입의 표현식 |
첨자 연산자 표현식은 lvalue 표현식 으로서, 그 타입은 pointer-expression 이 가리키는 객체의 타입입니다.
정의에 따르면, 첨자 연산자 E1 [ E2 ] 는 정확히 * ( ( E1 ) + ( E2 ) ) 와 동일합니다. 만약 pointer-expression 이 배열 표현식인 경우, 이는 lvalue-to-rvalue conversion 을 거쳐 배열의 첫 번째 요소를 가리키는 포인터로 변환됩니다.
포인터와 정수 간의 덧셈 정의 에 따라, 그 결과는 integer-expression 의 결과와 동일한 인덱스를 가진 배열 요소입니다 (또는, pointer-expression 이 어떤 배열의 i번째 요소를 가리키고 있었다면, 결과의 인덱스는 i에 integer-expression 의 결과를 더한 값입니다)
참고: 다차원 배열에 대한 자세한 내용은 array 를 참조하십시오.
#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 }
출력:
3 3 4 5 6 6 c c
역참조
dereference 또는 indirection 표현식은 다음과 같은 형태를 가집니다
*
포인터-표현식
|
|||||||||
여기서
| pointer-expression | - | 모든 포인터 타입의 expression |
만약 pointer-expression 이 함수에 대한 포인터라면, 역참조 연산자의 결과는 해당 함수에 대한 함수 지정자입니다.
만약 pointer-expression 가 객체에 대한 포인터인 경우, 결과는 가리키는 객체를 지정하는 lvalue expression 입니다.
널 포인터, 수명이 끝난 객체를 가리키는 포인터(댕글링 포인터), 잘못 정렬된 포인터, 또는 불확정 값을 가진 포인터를 역참조하는 것은 정의되지 않은 행위입니다. 단, 역참조 연산자의 결과에 주소 연산자를 적용하여 무효화하는 경우(예: & * E )는 예외입니다.
출력:
*p = 1 *p = 7
주소 연산자
주소 연산자 표현식의 형식은 다음과 같습니다
&
function
|
(1) | ||||||||
&
lvalue-expression
|
(2) | ||||||||
&
*
expression
|
(3) | ||||||||
&
expression
[
expression
]
|
(4) | ||||||||
`, `
`, `
&
와
*
는 서로 상쇄되며, 둘 중 어느 것도 평가되지 않음
&
와
[]
에 내포된
*
는 서로 상쇄되며,
[]
에 내포된 덧셈만 평가됩니다.
여기서
| lvalue-expression | - | lvalue 이며 bit-field 가 아니고 register 저장 클래스를 가지지 않는 모든 타입의 표현식 |
주소 연산자는 피연산자의 비-좌측값 주소를 생성하며, 피연산자 타입의 포인터를 초기화하는 데 적합합니다. 피연산자가 함수 지정자 (1) 인 경우, 결과는 함수에 대한 포인터입니다. 피연산자가 객체 (2) 인 경우, 결과는 객체에 대한 포인터입니다.
피연산자가 역참조 연산자인 경우, 아무런 동작도 수행되지 않습니다 (따라서 &*를 널 포인터에 적용해도 괜찮습니다). 단, 결과는 lvalue가 아닙니다.
피연산자가 배열 인덱스 표현식인 경우, 배열-포인터 변환과 덧셈 외에는 아무런 동작이 수행되지 않으므로, 크기가 N인 배열에 대해 &a[N]은 유효합니다 (끝을 지난 위치의 포인터를 얻는 것은 가능하지만, 역참조는 불가능합니다. 그러나 이 표현식에서는 역참조가 상쇄됩니다).
int f(char c) { return c;} int main(void) { int n = 1; int *p = &n; // 객체 n의 주소 int (*fp)(char) = &f; // 함수 f의 주소 int a[3] = {1,2,3}; int *beg=a, *end=&a[3]; // end = a+3과 동일 }
멤버 접근
멤버 접근 표현식의 형식은 다음과 같습니다
expression
.
member-name
|
|||||||||
여기서
| expression | - | struct 또는 union 타입의 표현식 |
| member-name | - | expression 으로 지정된 struct 또는 union의 멤버를 지정하는 식별자 |
멤버 접근 표현식은 왼쪽 피연산자가 지정하는 struct 또는 union 의 명명된 멤버를 지정합니다. 이 표현식은 왼쪽 피연산자와 동일한 value category 를 가집니다.
왼쪽 피연산자가 const 또는 volatile 한정자를 가지면 결과도 동일하게 한정됩니다. 왼쪽 피연산자가 atomic 인 경우, 동작은 정의되지 않습니다.
참고: 구조체 또는 공용체 타입의 객체를 명명하는 식별자 외에도, 다음 표현식들이 구조체 또는 공용체 타입을 가질 수 있습니다: assignment , function call , comma operator , conditional operator , 그리고 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; // 정상: s의 멤버를 변경함 int n = f().x; // f()는 struct s 타입의 표현식 // f().x = 1; // 오류: 이 멤버 접근 표현식은 lvalue가 아님 const struct s sc; // sc.x = 3; // 오류: sc.x는 const이며 할당할 수 없음 union { int x; double d; } u = {1}; u.d = 0.1; // union의 활성 멤버를 변경함 }
포인터를 통한 멤버 접근
멤버 접근 표현식의 형식은 다음과 같습니다
표현식
->
멤버-이름
|
|||||||||
여기서
| expression | - | pointer 타입의 표현식으로 struct 또는 union 을 가리킴 |
| member-name | - | identifier 로, expression 이 가리키는 struct 또는 union의 멤버 이름 |
멤버 접근 포인터 표현식은 왼쪽 피연산자가 가리키는 struct 또는 union 타입의 명명된 멤버를 지정합니다. 이것의 값 범주는 항상 lvalue 입니다.
왼쪽 피연산자가 가리키는 유형이 const 또는 volatile 로 한정된 경우, 결과도 동일하게 한정됩니다. 왼쪽 피연산자가 가리키는 유형이 atomic 인 경우, 동작은 정의되지 않습니다.
#include <stdio.h> struct s {int x;}; int main(void) { struct s s={1}, *p = &s; p->x = 7; // 포인터를 통해 s.x의 값을 변경 printf("%d\n", p->x); // 7을 출력 }
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| DR 076 | C89 |
불필요한 간접 참조를
&
로 취소할 수 없음
|
취소 가능하도록 변경됨 |
참조문헌
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.5.2.1 배열 첨자 (p: 57-58)
-
- 6.5.2.3 구조체 및 공용체 멤버 (p: 58-59)
-
- 6.5.3.2 주소 및 간접 연산자 (p: 59-61)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.5.2.1 배열 첨자 (p: 80)
-
- 6.5.2.3 구조체 및 공용체 멤버 (p: 82-84)
-
- 6.5.3.2 주소 및 간접 연산자 (p: 88-89)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.5.2.1 배열 첨자 연산 (p: 70)
-
- 6.5.2.3 구조체 및 공용체 멤버 (p: 72-74)
-
- 6.5.3.2 주소 및 간접 참조 연산자 (p: 78-79)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.3.2.1 배열 첨자
-
- 3.3.2.3 구조체 및 공용체 멤버
-
- 3.3.3.2 주소 및 간접 연산자
참고 항목
| 일반 연산자 | ||||||
|---|---|---|---|---|---|---|
| 대입 |
증가
감소 |
산술 | 논리 | 비교 |
멤버
접근 |
기타 |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
C++ documentation
for
Member access operators
|