일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- Bandit
- Hacking #Baic
- HTML #핵심정리
- C++ 언어 #핵심정리
- C언어 # 핵심 정리
- C++ 언어 # 핵심 정리
- shell_script
- C++ 언어 # 핵심정리
- C언어 #핵심정리
- PHP #핵심정리
- C언어 #부록
- C언어 # 부록
- MySQL #핵심정리
- Today
- Total
cCcode
C Language [핵심정리] - 35 본문
1. 포인터 연산 사용하기
포인터 연산은 포인터 변수에 + or - 연산자를 사용합니다. 단 / or * 연산자와 실수 값은 사용할 수 없습니다.
포인터 연산은 포인터 자료형의 크기만큼 더하거나 빼는 연산을 수행합니다. 그렇기 때문에 + 1을 한 주소값이 0000006AEAB7FC19가 아닌 0000006AEAB7FC1C가 나오게 되는 겁니다. 즉, Ptr_A + 1의 의미는 메모리 주소에서 int(4byte)만큼 1번 순방향으로 이동한다는 의미입니다.
□ 계산식 : sizeof(자료형) * 더하거나 빼는 값
이해를 못하셨을 분들 위해 간단히 설명해드리자면
일단 %p 서식지정자는 포인터의 메모리 주소(값을 16진수 8자릿수로 해석)를 출력할 때 사용하는 서식지정자 입니다.
그러면 16진수을 사용한다는 말과 동일합니다.
16진수란?16을 기수로 하는 번호체계로 숫자 0 ~ 9, 알파벳 A ~ F 를 이용해 표기합니다.ex) 0 1 2 3 4 5 6 7 8 9 A B C D E F
이런 식으로 표기하기 때문에 0000006AEAB7FC18에서 + 4 를 하면 9(1), 10(2) - A, 11(3) - B, 12(4) - C 가 되는겁니다.
포인터 연산 (뺄셈) 역시 동일한 원리로 동작합니다.
다만 포인터의 연산(뺄셈)은 주솟값이 감소, 즉 역행(backward)하기 때문에 배열의 첫 번째가 아닌 요소의 주소부터 연산을 시작했습니다. 이 때는 배열 자체가 첫번째 요소의 주소를 제외하곤 가지고 있지 않기에 주소연산자를 통해 주소 넘겨줘야 합니다.
만약 여러분들이 결과를 보는 도중
배열의 메모리 주소들은 끝부분 2자릿수만 달라진다는 점을 알아내서 [배열의 변수들은 모두 메모리에 나란히 나열되어있음]을 이라는 결과를 도출하셨다면... 대단하다는 말밖에 드릴 말이 없네요.
이 사실을 응용하면 배열의 메모리 주소를 포인터 +1 연산하면 다음 인덱스의 요소에 접근(역참조)할 수 있다는 점을 알아내실 수 있습니다.
만약 포인터 연산을 한후 출력할 때 다시 역참조하는게 조금 귀찮다.. 하시는 분들은 출력함수에 *(포인터 +- 값)을 통해서 바로 포인터 연산 후 그 결과를 역참조 해 출력할 수 있습니다.
이렇게 되면 코드의 길이와 변수의 선언 횟수를 줄일 수 있다는 장점이 있으나 가독성이 떨어진다는 단점 또한 존재합니다.
void 포인터는 자료형의 크기가 정해져있지 않기 때문에 +, -로 연산해도 얼마나 이동할지 알 수 없습니다. 따라서 포인터 연산 또한 불가능하죠.
이 경우 void 포인터를 다른 포인터로 변환한 뒤 연산하면 됩니다.
이 때 포인터 연산의 기준은 당연히 변환시킨 자료형입니다. 아차, 말씀드리지 않은게 메모리 해제할 때 free 함수로 메모리주소가 바뀐 포인터를 사용하면 에러 걸립니다. 그러니 해제할 때는 반드시 처음 메모리를 할당받은 주소를 사용해주세요. 그러니까 포인터 변수를 하나 선언해서 그 변수에 포인터의 원본 주소를 임시로 저장하는게 현명한 방법입니다.
+ C언어 표준에서 자료형 변환은 L-value 를 생성하지 않는다고 규정되어 있습니다. L-value는 메모리 공간을 차지하는 표현식을 뜻하며 R-value는 L-value 이외의 표현식을 뜻합니다.
이해하기 어렵다면 변수를 선언할 때의 위치를 생각하면 되요. l-value는 변수 선언의 왼쪽에 위치한 변수를 의미하며, r-value는 변수 선언 오른쪽에 위치한 literal 값을 의미합니다.
이외에도 구조체 포인터 또한 포인터 연산이 가능합니다. 구조체 포인터는 포인터 연산 한 부분을 괄호로 묶어준 뒤 ->(화살표 연산자)를 사용해 멤버에 접근하면 됩니다.
결론만 내자면 (Ptr1 + 1)->num 은 구조체 배열 인덱스로 접근하는 d1[1].num 과 동일한 역할을 합니다.
구조체 포인터의 경우 구조체 하나를 하나의 변수로 보기 때문에 구조체의 전체크기가 기준이 됩니다.
2. 함수 사용하기
C언어에서는 함수(function)이라는 기능을 제공합니다. 함수는 특정 용도의 코드들을 한 곳에 모아 놓은 것을 의미합니다.
함수를 정의하는 방법은 반환값, 자료형, 함수이름, 괄호 순으로 명시한 뒤 중괄호 안에 원하는 코드를 작성하면 됩니다.
(자세한 내용은 다음 글에서 다루겠습니다.)
'C Language Basic' 카테고리의 다른 글
C Language [핵심정리] - 37 (0) | 2021.07.11 |
---|---|
C Language [핵심정리] - 36 (0) | 2021.07.09 |
C Language [핵심정리] - 34 (0) | 2021.07.01 |
C Language [핵심정리] - 33 (0) | 2021.06.29 |
C Language [핵심정리] - 32 (0) | 2021.06.27 |