728x90
728x90
SMALL
포인터와 배열 이름은 일맥상통하는게 있다.
int array[5] = {0, 1, 2, 3, 4};
int * ptr = array;
배열의 이름 👉🏻 포인터 상수나 마찬가지. $($변하지 않는 주소 값$)$
- array 와 &array[0] 은 같다.
ο 배열의 이름 👉🏻배열의 첫번째 원소의 주소 - *array 와 array[0] 은 같다.
ο *array 👉🏻 배열의 첫번째 원소를 간접 참조함. - int * ptr = array;
ο ptr 포인터 변수가 array 배열의 주소를 담게 되었으니 이제 ptr로 array 배열에 간접참조가 가능해짐.
ο *ptr 와 array[0] 은 같다.
ο *ptr = 100 은 array[0]=100 과 같다.
■ 배열의 주소를 복사해 담은 포인터로 배열의 원소 값을 이렇게 바꿀 수도 있지만 char * 형 포인터에
char [] 문자열 배열의 원소를 바꾸려는 시도는 불가능하다. [다다음 포스트 참고]
배열의 이름과 포인터의 차이
int array[5] = {0, 1, 2, 3, 4};
int * ptr = array;
sizeof(array) // 👉🏻 20
sizeof(ptr)) // 👉🏻 4
- sizeof에 배열의 이름을 넣으면 배열의 총 메모리 크기를 알려주지만
- sizeof에 포인터를 넣으면 포인터가 배열을 가리키고 있더라도 포인터의 크기만 알려준다.
ο 포인터의 크기는 int * 든 double * 든 데이터 타입에 상관없이 4byte. $($64 bit 환경에선 8byte$)$
함수 파라미터로 배열을 넘길 때
void printArray(int * array)
{
cout << sizeof(array) << endl;
// 지역변수 array에 배열의 이름이 들어오든 포인터가 들어오든 지역변수 array는 포인터이므로 언제나 4가 출력될 것.
}
int main()
{
int array[5] = {0, 1, 2, 3, 4};
int * ptr = array;
printArray(array); // 배열의 주소가 printArray 함수 내부의 array 지역변수에 대입된다.
printArray(ptr); // 포인터 ptr 값이 printArray 함수의 지역변수 array에 대입된다.
}
- 함수의 매개변수로 배열을 전달할 때는 포인터로서 전달 된다. $($주소만 복사되어 넘어감$)$
ο 성능 상 이유로 매개변수 타입 자체를 배열로 하여 배열을 통째로 복사하여 넘기는 것은 금지되어 있다.
ο 배열 크기가 클때는 배열 복사하는데 시간이 많이 소요되기 때문.
ο 매개변수를 포인터로 선언해서 배열의 이름 $($= 배열의 첫번째 원소의 주소$)$만 복사하여 넘겨주면
포인터로 배열 원소에 접근할 수 있으므로 효율적이다.
■ 어차피 배열 원소들은 연속된 메모리 공간으로 위치하므로 첫번째 원소 주소값 $($= 배열의 이름$)$만
알면 다른 원소들도 4 $($int 기준$)$ 씩만 더해주어 주소를 알아낼 수 있다. - 이처럼 배열의 주소를 포인터 매개변수로 넘길 땐 포인터 매개변수만으로는 배열의 크기를 알 수 없으므로 int len 형태로 배열의 크기를 직접 같이 넘겨주어야 한다.
void printArray(int * array, int len)
매개변수가 배열 같아 보여도 사실 포인터다.
void printArray(int array [5])
{
cout << sizeof(array) << endl;
}
int main()
{
int array[5] = {0, 1, 2, 3, 4};
int * ptr = array;
printArray(array);
printArray(ptr);
}
void printArray(int array [5])
- 매개변수를 배열로 받는 것 같아 보여도 사실 포인터다.
ο 배열을 위한 포인터라고 [ ] 대괄호 기호를 써서 배열의 주소를 넘겨 받을 것임을 강조하는 것 뿐
ο 오직 매개변수 타입에서만 * 를 [ ] 로 바꾸는 것이 가능하다.
■ 더블포인터와 같이 * 가 여러개인 경우엔 하나만 [ ] 로 바꿀 수 있다.
void func(int ** pArr) // 가능
void func(int * pArr[]) // 가능
void func(int pArr[][]) // 불가능
- 따라서 [ ] 기호 안의 숫자도 아무 의미 없다.
실제로 3 크기의 배열을 넘기는 것이라도 매개변수에 [5]라고 되있다고 해서 오류가 발생하는 것도 아니다. - 프로그램에는 영향을 미치지 않고 단순 5 크기의 배열을 받을 것이라는 표시일뿐.
구조체 혹은 클래스의 멤버로 속한 배열을 매개변수로 넘길 때
이 경우엔 포인터로 전환되지 않고 배열 자체가 그대로 넘겨진다.
#include <iostream>
#include <cstring>
using namespace std;
struct Mystruct
{
int array[5] = { 9, 7, 5, 3, 1 };
};
void doSomething(Mystruct * ms)
{
cout << sizeof((*ms).array) << endl; // 4가 아닌 20 출력
}
int main()
{
Mystruct ms;
cout << ms.array[0] << endl; // 9 출력
cout << sizeof(ms.array) << endl; // 20 출력 (멤버가 array 배열 하나 뿐)
doSomething(ms);
return 0;
}
- 배열이 구조체나 클래스의 멤버로 있을 땐
ο 파라미터가 구조체 타입으로 받든 구조체 포인터로 받든
ο 배열 그 자체가 넘어간다
■ 위와 같이 배열의 주소가 포인터에 복사되어 넘어가는 것이 아닌!
728x90
300x250
LIST
'C │ C++ │ C# > C++' 카테고리의 다른 글
C++ Chapter 6.9 : C언어 스타일의 문자열 기호적 상수 (1) | 2023.10.29 |
---|---|
C++ Chapter 6.8 : 포인터의 연산과 배열 인덱싱 (2) | 2023.10.15 |
C++ Chapter 6.6 : 포인터의 기본적인 사용법 (0) | 2023.09.04 |
C++ Chapter 6.5 : C언어 스타일의 배열 문자열 (0) | 2023.09.03 |
C++ Chapter 6.4 : 정적 다차원 배열 (0) | 2023.08.31 |