일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 데이터애셋
- 정렬알고리즘
- stl
- map
- BFS
- enumasByue
- 자료구조
- 약참조
- 프로그래머스
- C++최적화
- 애셋로드
- 크리티컬섹션
- 알고리즘
- UELOG
- 언리얼엔진구조체
- 정렬
- dataasset
- 람다사용정렬
- 강참조
- moreeffectiveC++
- 선택정렬
- 델리게이트
- 스마트포인터
- 람다
- 언리얼가비지컬렉터
- UE4 커스텀로그
- unorder_map
- UE_LOG
- UML관련
- C++
- Today
- Total
기억을 위한 기록들
[Fundamental C++] 4. 포인터 본문
- 메모리의 주소를 가리키는 객체를 포인터라고 부른다.
- 메모리 블록은 주소, 크기, 상태의 정보를 가지고 있다.
- 메모리 블록을 쉽게 관리할 수 있도록 포인터에는 주소뿐 아니라 타입 정보까지 들어가게 되었다.
타입 정보를 통해 메모리 주소로부터 타입 크기만큼 블록에 값을 읽거나 쓸 수 있게 된 것이다.
포인터 타입
- int 타입 객체를 기리 키기 위해 int* 타입 포인터를 사용하는 것이 쉽게 편해서 장점이 많다는 것이지, 반드시 int* 을 사용해야만 하는 것은 아니다. 필요에 따라 다른 타입이 int타입을 가리킬 수도 있다.
같은 경우
int a = 0;
int* ptr = &a;
*ptr = 3; //역참조 값 변경
std::cout<< a << std::endl; //3 출력
다른 경우
int a = 0;
char* ptr = &a; // 컴파일 에러!
char* ptr = (char*)&a; //성공
타입이 다르기에 컴파일 에러가 발생하게 되고, 강제 타입 변환으로 성공하였다. 이어서 같은 경우에서와 같이 역참조를 해줄 경우
int a = 0;
char* ptr = &a; // 컴파일 에러!
char* ptr = (char*)&a; //성공
*(ptr + 0) = 'A';
*(ptr + 1) = 'B';
*(ptr + 2) = 'C';
*(ptr + 3) = '\0';
char는 1바이트 단위로만 메모리 블록에 값을 쓸 수 있다. 따라서 a가 가리키는 4바이트(int) 메모리 블록에 각각 값을 쓰기 위해서 (ptr + 0), (ptr + 1), (ptr + 2), (ptr + 3)으로 4번에 걸쳐서 메모리 블록에 접근해야 한다.
- 각각 0, 1, 2, 3을 더했는데 해당 바이트만큼 이동한다는 의미가 아니라 sizeof(char) 크기의 0 배수, 1 배수, 2 배수, 3 배수만큼씩 이동한다는 의미이다. 그리고 각각의 1바이트 블록에 A, B, C,\0을 대입했다. 마지막 \0을 문자열 종료 표시이다.
int a = 0;
//char* ptr = &a; // 컴파일 에러!
char* ptr = (char*)&a; //성공
*(ptr + 0) = 'A';
*(ptr + 1) = 'B';
*(ptr + 2) = 'C';
*(ptr + 3) = '\0';
cout << (char*)&a << endl; //ABC 출력
cout << *ptr << endl; //A 출력
- 예제를 통해서 확인할 수 있듯이 포인터의 원시 타입은 포인터가 가리키는 메모리 주소로부터 타입 크기만큼의 블록을 타입 기준으로 읽고, 쓰기 위해서 사용된다.
즉, 어떤 TYPE* ptr 이 나타내는 의미는 ptr가 가리키는 주소를 기준으로 sizeof(TYPE) 크기의 블록의 비트 상태를 TYPE에 의해서 의미(값)를 부요하여 대응시키겠다는 것이다. 따라서 ptr를 통해 해당 블록의 값을 읽거나 쓸 수 있다.
배열 포인터 타입
- typedef를 이용한 배열의 포인터 타입 나타내기.
#include <iostream>
using namespace std;
typedef int(TARR)[2];
typedef int(*PARR)[2];
int arr[2] = { 1,2 };
int main()
{
TARR* ptr = &arr;
PARR ptr2 = &arr;
cout << (*ptr)[0] <<", "<<(*ptr)[1]<< endl;
cout << (*ptr2)[0]<<", " <<(*ptr2)[1]<< endl;
return 0;
}
- typedef 사용하지 않고 배열의 포인터 타입 나타내기
#include <iostream>
using namespace std;
template<typename T>
void ArrayPrint(T arg)
{
cout << (*arg)[0] <<", "<< (*arg)[1] << endl;
}
int main()
{
int arr[2] = { 3,4 };
ArrayPrint<int(*)[2]>(&arr);
return 0;
}
- 함수의 포인터 타입 살펴보기
#include <iostream>
using namespace std;
int DoSomething(int arg)
{
return arg;
}
template<typename T>
void CallFunc(T arg)
{
cout << arg(15)<< endl;
}
int main()
{
CallFunc<int(*)(int)>(DoSomething);
return 0;
}
'C & CPP > Fundamental C++' 카테고리의 다른 글
[Fundamental C++] 6. 클래스 (1) - 메모리구조, 크기 (1) | 2021.04.29 |
---|---|
[Fundamental C++] 5. 배열 (0) | 2021.04.27 |
[Fundamental C++] 3. 메모리 (0) | 2021.04.27 |
[Fundamental C++] 2. 빌드 (0) | 2021.04.27 |
[Fundamental C++] 1. 선언과 정의 (0) | 2021.04.27 |