void 포인터는 C와 C++ 프로그래밍 언어에서 사용되는 특별한 종류의 포인터로, 어떤 데이터 타입도 가리킬 수 있는 포인터입니다. "void"는 본래 "빈" 또는 "비어 있음"을 의미하며, void 포인터는 특정한 데이터 타입을 가리키지 않기 때문에 다양한 용도로 활용될 수 있습니다.
void* pVoid = nullptr;
int a = 0;
char c = 0;
short ss = 0;
pVoid = &a;
pVoid = &c;
pVoid = &ss;
// 메모리 복사 함수
void CopyData(void* _Dest, void* _Src, unsigned int _Size)
{
unsigned char* pDest = (unsigned char*)_Dest;
unsigned char* pSrc = (unsigned char*)_Src;
for (int i = 0; i < _Size; ++i)
{
//*(pDest + i) = *(pSrc + i);
pDest[i] = pSrc[i];
}
}
void 포인터 변수에 들어있는 주소값을 다른 일반 포인터에 옮길 수 없다.
현재 Short Type 변수를 void pVoid Pointer에 선언하엿지만 이를 int Type pIntPtr에 선언하면 Short Type 변수의 주소를 Int Type에 선언하는 것이기 대문에 옮길 수 없다.
int* pIntPtr = pVoid;
// 포인터와 구조체
MyDataType data = {};
MyDataType* pData = &data;
(*pData).i = 10;
(*pData).f = 1.1f;
pData->i = 10;
pData->f = 1.1f;
data.i = 10;
data.f = 1.1f;
일반적인 구조체에는 Instance.Member Variable 로 접근한다. 하지만 Struct Pointer는 (*pData).i = 10; 와 같은 형식으로 접근하는데 이를 ->로 축약해서 사용 할 수 있다.
이것과 관련된 내용은 저번 Pointer 공부글에서 다양한 예시를 확인 할 수 있다.
//정상
data.i = 10;
//비정상
~~pData.f = 1.1f;~~
Struct Pointer로 일반적인 Struct 접근 방식을 사용하면 오류가 발생한다.
Test의 답은 무엇일까?
Pointer에 대해 이해하고 있다면 맞출 수 있는 문제이다. (처음에는 틀렸다.)
short Test()
{
short arrShort[20] = {};
for (int i = 0; i < 20; ++i)
{
arrShort[i] = i + 1;
}
int* pInt = (int*)arrShort;
pInt += 4;
//short* pShort = (short*)pInt;
//return *pShort;
return *((short*)pInt);
}
처음에는 해당 문제의 답이 "Compile Error"라고 생각했다. 그 이유는 처음에 short 선언 한 것을 (int*)로 형변환을 했으니 오류가 나지 않았을까? 2비트 -> 4비트 변경이니 이건 return 되지 않고 중간에 오류로 끝나겠다. 라고 생각한 것이 이유였다. 하지만 이건 완전히 잘못된 접근이였다.
첫 번째로 Test문제에서 short Type로 선언된 것은 배열이다. 하지만 한가지 생각해야 할 것은 배열(Array)는 Pointer와 밀접한 관련이 있다는 것이다. 배열은 메모리 주소 체계를 이용하여 데이터를 저장하고 관리한다. 흔히 배열에 접근하는 방식은 메모리 접근과 동일하다.
#include <iostream>
int main() {
int Array[10] = {0}; // 배열의 모든 요소를 0으로 초기화
int *p = Array; // p는 Array의 첫 번째 요소를 가리킵니다
// 포인터 연산을 사용하여 배열의 5번째 요소(인덱스 4)에 접근하고 값을 더하기
*(p + 4) += 10; // Array[4]에 10을 더합니다
std::cout << "Array[4] after adding 10: " << Array[4] << std::endl;
// 포인터 연산을 사용하여 배열의 5번째 요소를 특정 값으로 설정하기
*(p + 4) = 5; // Array[4]에 5를 대입합니다
std::cout << "Array[4] after setting to 5: " << Array[4] << std::endl;
return 0;
}
Short Type의 배열을 선언하고 각 주소에 접근해 i+1의 값을 넣었다. 그렇다면 아래 숫자가 담긴 한칸 한칸은 Short Type의 크기인 2비트이다.
다음은 Short 타입으로 선언된 배열을 int 타입으로 형변환 해주었는데 이는 오류가 나나?
주소 크기를 다르게 보는것인데 왜 오류?
Short타입에서 int 타입으로 바꿨으니까 오류가 나지
그건 short 타입 변수 short i = 2 인 것을 변환할때 오류가 나는 거지 이건 주소 접근 체계이다.
여기서 pInt +=4라는 의미에 대해 해석해보자.
pInt는 포인터로 arrShort라는 배열의 0번째 인덱스를 가르킨다. pInt+=4 라는 의미는
pInt에서 4비트를 증가한 2에 접근하라는 의미가 아니다. <- 처음에 이렇게 생각했다.
포인터 +=4는 배열의 4번째 index에 접근하라는 의미이다. 이건 현재 int Type 배열인 arrShort의 4번째 index인 9에 접근하라는 의미로 해석될 수 있는 것이다.
이것을 마지막에 Short형태로 형변환을 하더라도 이미 접근은 끝마쳤기 때문에 답이 9인것은 변함이 없다.
상수를 가리키는 포인터 (Pointer to const value)
상수를 가리키는 포인터는 상수 변수의 주소를 가리키는 (non-const) 포인터다.
const int value = 5;
const int* ptr = &value; // this is okay, ptr is a non-const pointer that is pointing to a "const int"
*ptr = 6; // not allowed, we can't change a const value
int value = 5;
const int* ptr1 = &value; // ptr1 points to a "const int", so this is a pointer to a const value.
int* const ptr2 = &value; // ptr2 points to an "int", so this is a const pointer to a non-const value.
const int* const ptr3 = &value; // ptr3 points to a "const int", so this is a const pointer to a const value.