배열의 이름
int arr[4] {}; 를 정의했을 때
cout << arr;
과
cout << &arr
의 출력은 같다는 걸 발견할 수 있다.
2018-02-18
arr은 0번째 원소의 주소를 담고있는 포인터 즉 [arr[0]의 타입]* 타입(여기선 int* 타입)
&arr은 arr의 주소를 담고있는 상수 포인터. 즉 [arr의 타입]* 타입이다. (컴파일러는 arr의 크기를 알고있음)
둘이 같은 이유는 arr은 배열의 첫 원소가 할당된 지점이고 &arr은 배열이 할당된 지점이기 때문이다.
2018-02-21
배열이름이 반드시 포인터인 것은 아니다! 단지 포인터로 decaying 할 뿐이다.
(출처 : https://stackoverflow.com/questions/1461432/what-is-array-decaying)
배열이름이 포인터로 디케잉 하지않는 특수상황 :
(https://stackoverflow.com/questions/17752978/exception-to-array-not-decaying-into-a-pointer)
1. when it's the argument of the & (address-of) operator.
2. when it's the argument of the sizeof operator.
3. When it's a string literal of type char [N + 1] or a wide string literal of type wchar_t [N + 1] (N is the length of the string) which is used to initialize an array, as in char str[] = "foo"; or wchar_t wstr[] = L"foo";.
배열의 이름은 첫 번째 원소를 가르키는 상수 포인터로 변환된다.
하지만 배열의 이름이 예외적으로 다르게 쓰이는 경우가 있는데 그중 하나는 sizeof(arr)과 같이 sizeof의 대상으로 쓰였을 때다.
(출처: https://en.wikipedia.org/wiki/Sizeof#Application_to_arrays)
cout << sizeof(arr) //16
cout << sizeof(&arr) //4
sizeof 에 배열의 이름을 쓸 수 있는 상황은 이미 컴파일러가 배열의 크기를 알고있는 상황이기 때문에,(C/C++의 컴파일러는 왜 배열의 크기를 알아야 할까?) sizeof는 &arr에 사용했을 때 처럼의 포인터 크기 4 대신 사용하는 배열 전체의 크기(여기선 4*4 16)를 출력한다.
그런데 arr + 1과 &arr + 1의 경우는 위와 느낌이 다르다.
위의 흐름대로라면 arr + 1은 배열 한칸의 크기를, &arr + 1이 4바이트 한 칸의 크기를 건너야 할 것 같지만 실상은 반대다.
arr의 주소가 1000이라고 할 때
arr + 1 == 1004
&arr + 1 == 1016이다.
&arr + 1이 배열 전체크기를 건너 뛸 수 있는 것도 arr의 크기를 컴파일러가 알고있을 때에만 가능한 결과다.
2018-02-18
arr + 1의 결과는 arr의 타입이 무엇이냐에 따라 다르다. 여기서 arr은 포인터인데 첫 번째 원소의 주소를 담는 포인터이므로 연산의 이동거리는 첫 번째 원소의 타입의 크기만큼이다.여기선 arr[0]은 int이므로 4바이트. + 연산의 결과(리턴값)는 &arr[0]에서 이동한 &arr[1]이다.
&arr도 상수 포인터인데 arr의 타입의 주소를 담는 포인터다. 여기서는 배열이므로 이때의 이동거리는 arr의 크기만큼이 될 것이다. (컴파일러가 알고있다면)
마지막으로 배열 이름을 함수의 인자로 넣는다면 함수 안에서는 그저 포인터로 취급(decaying)될 뿐이다. 이 때 포인터도 복사가 되기에 &arr은 복사된 포인터의 주소라는걸 기억하자.
다음은 공부를 위해 테스트를 진행한 코드. (별로 중요하지 않음)
void testA(int a[])
{
cout << "\n testA 함수 내의 작동 :\n";
cout << a << endl;
cout << a + 1<< endl;
cout << &a << endl;
cout << &a + 1 << endl;
cout << "------\n";
}
int main()
{
int arr[4] = { 0, 1, 2 };
cout << "arr : " << arr << endl;
cout << "arr + 1 : " << arr + 1 << endl;
cout << "&arr + 1 : " << &arr + 1 << endl;
cout << "&arr + 1 - &arr : " << int(&arr + 1) - int(arr) << endl;
testA(arr);
cout << sizeof(arr) << endl;
cout << sizeof(&arr) << endl;
return 0;
}
실행결과:
'프로그래밍 > C, C++ 공부' 카테고리의 다른 글
문자열로 입력된 연산문의 분석 (0) | 2018.02.17 |
---|---|
이중배열, N중배열 (0) | 2018.02.17 |
C/C++의 컴파일러는 왜 배열의 크기를 알아야 할까? (0) | 2018.02.16 |
정수의 자릿수 구하기, 한 자리씩 판별하기 (0) | 2018.02.16 |
for문을 사용할 때 (0) | 2018.02.15 |