일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- CSS
- C
- 선형대수학
- html
- 프로그래밍
- 물리학
- html5
- Java
- 나무위키
- javascript
- python
- LaTeX
- 리브레위키
- ┌─┐
- 자바스크립트
- matlab
- 점자
- 글이_점점_짧아지고_있습니다.
- Inkscape
- css3
- HTML5.
- C언어
- 확률
- Nemeth Braille
- 오늘의 문제
- 프로그래밍 언어
- 위키
- C++
- 수학
- IT
- Today
- Total
SturdyCobble's Study Note
[프로그래밍] 6.4 포인터와 배열 (1) 본문
NOTICE : 독학인 만큼, 잘못된 내용이 있을 수 있습니다. 내용 지적은 언제나 환영합니다.
더 이상 이 블로그에는 글을 올리지는 않을 예정입니다. 그렇지만 댓글을 달아주시면 최대한 답변드리고자 노력하겠습니다.
※이 글은 프로그래밍 언어에 대한 기초적인 이해를 가정하고 있습니다. 최소 프로그래밍 언어 하나 정도를 약간이라도 접해보시는 것을 추천합니다. 또한, 이 글은 심화 내용은 되도록 피하여 서술했습니다.
포인터는 C/C++에 존재하는 개념입니다. 포인터에 대한 설명을 Wikipedia에서 가져와 봤습니다.
밍 언어에 대한 기초적인 이해를 가정하고 있습니다. 최소 프로그래밍 언어 하나 정도를 약간이라도 접해보시는 것을 추천합니다. 또한, 이 글은 심화 내용은 되도록 피하여 서술했습니다.
포인터는 C/C++에 존재하는 개념입니다. 포인터에 대한 설명을 Wikipedia에서 가져와 봤습니다.
■ pointer is a programming language object that stores a memory address.
■ A memory pointer (or just pointer) is a primitive, the value of which is intended to be used as a memory
address; it is said that a pointer points to a memory address.
■ More generally, a pointer is a kind of reference, and it is said that a pointer references a datum stored
somewhere in memory; to obtain that datum is to dereference the pointer. The feature that separates
pointers from other kinds of reference is that a pointer's value is meant to be interpreted as a memory
address, which is a rather low-level concept.
(From https://en.wikipedia.org/wiki/Pointer_(computer_programming))
그리고 여기에 존재하는 reference의 개념은 다음과 같이 정의되어 있었습니다.
■ In computer science, a reference is a value that enables a program to indirectly access a particular datum.
(From https://en.wikipedia.org/wiki/Reference_(computer_science))
위의 내용을 요약해보자면, 포인터는 메모리 주소(memory address)를 저장하는 것으로서, 이를 통해 특정 데이터에 대한 간접적인 접근을 가능하게 한다고 볼 수 있겠습니다. 그리고 이는 넓은 의미에서 reference에 포함됩니다.
그런데, C++, Java에는 또다른 reference의 개념이 있습니다. 여기서 reference 개념은 보다 좁은 의미의 개념으로 볼 수 있습니다. 이러한 흐름을 요약해보자면 다음과 같이 그려볼 수 있겠습니다. (관련 내용은 이후 다른 글에서 다루어보겠습니다.)
하지만, 이러한 구현은 컴파일러나, 운영 환경, 언어와 버전마다 다를 수 있음을 알아두어야 합니다. 또한, 정의하기 나름이겠지만 Reference가 넓은 의미에서 저 두가지만을 포함하는 것은 아닙니다. 그리고 분류하기 나름이겠지만, C++의 Reference에는 없는 C++의 Pointer와 Java의 Reference의 공통점이 존재하기도 합니다.
서론이 길었지만, 결국 포인터는 (적어도 C/C++에서는) 메모리 주소를 저장하여, 특정 데이터에 간접적으로 접근할 수 있게 해주는 것이라 할 수 있습니다. 이러한 포인터 변수를 만든다고 생각하면, 일반적인 변수 선언과 함께, 이게 포인터라는 점, 그리고 어떤 데이터를 가리킬 것이라는 점을 알려줘야 할 것입니다.
특별히 그 데이터가 어떤 데이터인지 알려주면, 변수의 크기가 다양하기 때문에, 시작하는 곳의 메모리 주소부터 시작해서 정확히 원하는 지점까지 가져올 수 있을 것입니다.
예를 들어, int형 (4 Byte) 변수 bar를 간접적으로 가리키는 포인터 변수 foo를 선언해 볼 수 있을 것입니다. 이는 코드 상에서는 다음과 같이 나타납니다. (bar는 위에 어딘가 선언되었다고 가정해봅시다)
int *foo;
foo = &bar;
여기서 첫번째 줄의 *는 연산자가 아니라, 그냥 포인터임을 알려주는 용도일 뿐입니다. 일종의 구두점으로서, 우리가 말하면서 ?나 !을 사용하는 것과 비슷한 느낌입니다.
두번째 줄은 foo라는 int형 포인터에 bar의 주소를 대입하는 식입니다. 여기서 &는 주소 연산자로, 변수의 주소를 얻기 위해 사용됩니다.
참고로 다음과 같은 식도 가능합니다. 이 경우, foo는 정수형 변수, bar는 정수형 포인터 변수가 됩니다.
int foo, *bar;
즉 *의 위치와 사이 공백의 유무는 의미차이를 주지 않습니다. 만약 둘다 포인터로 만들고 싶다면, ' * '을 두 번 사용해야 할 것입니다.
포인터의 개념을 말하면서, 간접적으로 데이터에 접근한다는 점을 위에서 언급했었습니다. 다시 그 값에 접근하기 위해서는 *연산자를 사용합니다. 여기서는 일종의 단항(Unitary) 연산자라고 볼 수 있습니다.
int bar = 10;
int *foo;
foo = &bar;
printf("%d",*foo);
선언할 때의 *는 일종의 구두점으로 값을 참조할 때 사용하는 *는 연산자로서 다른 의미를 가집니다. 아래 구문은 따라서 가리키는 값에 주소값을 집어넣는 게 아니라, 포인터 변수를 초기화하는 예시가 됩니다. (애초에 가리키는 값에 주소값을 집어넣는 다는 이야기 자체가 성립하지 않습니다.)
int bar = 100;
int *foo = &bar;
// int *foo; foo = &bar; 와 동일
포인터가 값을 저장하지 않는다는 사실은 직접 그 값을 출력해 보면 확인할 수 있습니다. 또한 그 크기를 구해봐도 확인할 수 있습니다.
그리고 아래 예시로 부터, 참조하는 변수의 값이 변화하면 가리키는 값도 당연히 변화하는 것을 확인할 수 있습니다.
# include <iostream>
using namespace std;
int main(){
int bar = 300;
int *foo = &bar;
__int64 big_bar = 300;
__int64 *bfoo = &big_bar;
cout << "*foo : " << *foo << ", sizeof(foo) : " << sizeof(foo) ;
cout << ", sizeof(bfoo) : " << sizeof(bfoo) << endl;
cout << "sizeof(*bfoo) : " << sizeof(*bfoo) << ", foo : " << foo << endl;
bar = 500;
cout << "*foo after the change in bar : " << *foo << endl;
}
-----------------RESULT-----------------
*foo : 300, sizeof(foo) : 4, sizeof(bfoo) : 4
sizeof(*bfoo) : 8, foo : 0x61ff04
*foo after the change in bar : 500
포인터 변수의 크기는 컴파일러나 운영환경, 그리고 CPU에 따라 달라집니다. 1 word만큼(CPU가 한 번에 처리하는 데이터 크기)을 사용하는 것이 일반적입니다. 이는 32비트 시스템에서는 32비트 = 4 바이트, 64비트 시스템에서는 64비트 = 8 바이트가 됩니다. 32비트 시스템은 32개 비트를 가지고 메모리의 주소를 표현하므로, 이렇게 설정하는 것이 합당해 보입니다.
(하지만, 운영체제에 따라 주소를 64비트로 표현하는 것이 아닌 더 작은 비트만으로 표현하기도 합니다. 이 경우 64비트에 해당하는 주소를 모두 차지할 만큼 메모리를 증설하는 것은 불가능합니다. 그리고 이러한 세부 사항은 컴파일러나 여러가지 조건에 좌우될 수 있습니다.)
다음 글에서는 본격적으로 포인터를 활용하고 연산하는 과정에 대해 알아보겠습니다.
'휴지통 > ['19.06-'20.07]프로그래밍101' 카테고리의 다른 글
[프로그래밍] 6.6 레퍼런스(Reference)와 포인터(Pointer) (0) | 2020.07.29 |
---|---|
[프로그래밍] 6.5 포인터와 배열 (2) (0) | 2020.02.23 |
[프로그래밍] 6.3 register, volatile & 메모리의 구조 (0) | 2020.02.13 |
[프로그래밍] 6.2 기억 부류 지정자 (2) (0) | 2020.01.25 |
[프로그래밍] 6.1 기억 부류 지정자 (1) (0) | 2020.01.20 |