포인터에 대한 좋은 설명은 무엇입니까? [닫은]


72

자신의 연구에서 (자신의 수업 또는 수업에 대한) 마지막으로 실제로 포인터를 이해했을 때 "ah ha"순간이 있었습니까? 특히 효과적인 초보자 프로그래머에 대한 설명이 있습니까?

예를 들어, 초보자가 C에서 처음 포인터를 만나면 컴파일 할 때까지 &s와 *s를 추가 할 수 있습니다 (내가 한 번했던 것처럼). 어쩌면 그것은 당신이나 당신의 학생을 위해 포인터를 "클릭"하게 만든 그림 또는 정말 동기가 좋은 예일 것입니다. 그게 뭐 였고, 그 전에 효과가 없었던 것 전에 무엇을 시도 했습니까? 주제 전제 조건 (예 : 구조체 또는 배열)이 있습니까?

즉,의 의미를 이해할 필요가 무엇 이었습니까 &들과 *안심을 사용할 수있을 때,? 구문과 용어 또는 사용 사례를 배우는 것만으로는 충분하지 않습니다. 어떤 시점에서는 아이디어를 내재화해야합니다.


업데이트 : 나는 지금까지 답변을 정말로 좋아합니다. 계속 오세요 여기에는 훌륭한 관점이 많이 있지만 개념을 내면화 한 후에 는 많은 사람들이 스스로 설명하고 슬로건이라고 생각 합니다. 나는 그것이 당신에게 떠오른 자세한 상황과 상황을 찾고 있습니다.

예를 들면 다음과 같습니다.

나는 C에서 문법적으로 포인터를 약간 이해했다. 나는 두 친구가 다른 친구에게 포인터를 설명하는 것을 들었다 struct. 첫 번째 친구는 ​​어떻게 참조하고 수정해야하는지에 대해 이야기했지만 다른 친구가 "더 효율적입니다"라는 짧은 친구의 의견이었습니다. 16 바이트 대신 4 바이트를 전달하는 것이 내가 마지막으로 필요로 한 개념적 전환이었습니다.


16
'Shotgun'방법 : 작동 할 때까지 어디서나 * s를 던지십시오.
Michael K

15
@ 마이클 : 그래, 행운을 빌어.
Robert Harvey

8
이 질문은 매 학기가 시작된 직후에 나타납니다. 최신 화신은 여기에 있습니다 : stackoverflow.com/questions/4118647/…
Tim Post

10
포인터에 대한 좋은 설명은 무엇입니까? Brian Kernhigan과 Dennis Ritchie는 소프트웨어 엔지니어를 싫어합니다.
Adam Crossland

3
디버거에서 한 단계 씩 스테핑 머신 코드를 보낸 후 "클릭"했습니다. 예, 저는 컴퓨터 아키텍처의 기본 사항에 익숙했습니다. Commodore 64에서 어셈블리를 배웠으며 그 후 x86 ASM은 매우 간단했습니다. 그래서 나는 이미 "주소"의 개념을 알고 있었는데, 그것이 그것이 C의 구문 구조에 어떻게 매핑되는지 이해하지 못했습니다.
zvrba

답변:


25

그리드로서의 메모리 다이어그램

일반적으로 내가하는 일은 메모리를 "그리드"로 나타내므로 주소를 구성하고 다른 메모리 공간을 강조 표시하며 셀 값 (또는 그 이진 표현)을 쓰고 메모리의 포인터를 값에 연결할 수 있습니다 가리킨다. (그리고 여전히 단순화라고 언급하십시오).

일반적으로 대부분의 학생들에게 "오"순간입니다.

심볼 저글링

그런 다음 & 및 * 사용법을 잊어 버릴 때 매우 간단합니다. 수학이나 물리 계산과 같은 방식으로 제시하십시오. 거리를 km 단위로 시간 단위로 나누면 km / h 단위의 속도를 얻습니다. 안에있는 것은 밖에 있어야합니다. 단순한.

구조에 printf

이것으로 당신이 설명한 것을 시각적으로 나타내는 몇 가지 기본 예제를 수행하면 그들이 이해한다고 생각하는 것을 위로하거나 "아, 나는 이것을 얻지 못한다"고 말할 기회를줍니다.

광범위하다

간단한 유형에 대한 포인터를 다루고 주소 지정과 데이터 유형의 크기, 구조체, 배열 및 여러 수준의 차이점을 이해해야합니다.

그런 다음 포인터 산술을 시작하십시오.


부록 : 재귀

나는 일반적으로 시각적 표현을 사용하여 재귀를 비슷하게 설명합니다. 한 문자를 쓰는 미리 만들어진 함수를 사용하여 알파벳을 인쇄 한 다음 두 줄만 바꾸면 역순으로 인쇄하도록 요청하십시오.

보통 "무엇이 ...?" 숫자 값을 인쇄하고 단계를 들여 쓰기 위해 printf에 다른 매개 변수 만 추가하면 안심할 수 있습니다.


대안 : Play-Doh 모델과 워터 컵

저는 실제로 대학에 동료들과 함께 플레이도 페이스트를 사용하여 포인터와 메모리 액세스를 설명하는 비디오를 보여주었습니다. 프로그래밍을 이해하는 데 관심이있는 아주 어린 학습자들을 제외하고는 그 기법을 실제로 사용하지는 않았지만 (정말 포인터를 너무 일찍 사용하여 언어로 이끌지 않을 것입니다) 정말 놀랍고 똑똑했습니다. 기본적으로 메모리 공간을 나타내는 다른 더 큰 play-doh 볼에 부착 할 수있는 작은 play-doh 볼을 사용하고 서로 결합하여 (링크 된 데이터 구조와 같이) 서로 연결하거나 (연속 된 것처럼) 병합 할 수 있습니다 메모리 공간). 가리키는 메모리 공간에 다른 색상을 사용하면 포인터도 도움이됩니다. 하지만 여전히 그리드로서의 메모리가 더 잘 작동한다고 생각합니다. "map / grid"에서와 같이 포인팅이 실제로 "주소 지정"의 문제임을 분명히 알 수 있습니다. Play-doh 모드는 여전히 메모리에서 사물이 서로 "접촉"한다고 생각하는 데 혼란을 겪습니다.

Water Cup은 동료가 직접 사용했지만 그녀가 그것을 생각해 냈는지 모르겠습니다. 흥미로운 접근 방식 이었지만 많은 학생들이 설명에 의지하는 것을 보았습니다. DevSolo의 커피 컵 기술과 비슷한 것 . 그러나 학생들이 컨테이너, 데이터 구조, 포인터 및 배열을 혼동하게 만들면 실제로 오해의 소지가 있다고 생각합니다. 필자가 처음에 배열을 설명하는 흥미로운 접근법 일지 모르지만 아주 오래 가지 않을 것입니다.


와우, 바운티 감사합니다. 답변이 기뻤습니다.
haylem

그것을 꺼내십시오 : | 좋은 가르침처럼 들립니다!
Spooks

80

내가 한 번보다 더 현명한 사람 :

우 Jincang 수녀는 여섯 번째 Patriach Huineng에게 물었다. "나는 Mahaparinirvana 경전을 수년 동안 연구 해 왔지만, 아직 이해하지 못하는 분야가 많이 있습니다. 제발 밝히십시오."

patriach는 "나는 문맹입니다. 저에게 문자를 읽어주세요. 아마도 그 의미를 설명 할 수있을 것입니다."라고 대답했습니다.

수녀는“캐릭터조차 인식 할 수 없습니다. 그러면 어떻게 그 의미를 이해할 수 있습니까?”라고 말했습니다.

"진실은 단어와 관련이 없습니다. 진실은 하늘의 밝은 달에 비유 될 수 있습니다.이 경우 단어는 손가락에 비유 될 수 있습니다. 손가락은 달의 위치를 ​​가리킬 수 있습니다. 그러나 손가락은 달을보기 위해서는 손가락 너머로 응시해야합니까? "


13
달을 역 참조하면 +1 내가 할 수 있다면 koan을 +1한다.
Tim Post

14
한 손가락으로 올리는 소리는 무엇입니까?
Adam Crossland

3
@Adam은 마우스를 사용하는지 트랙 패드를 사용하는지에 따라 다릅니다.
Daniel Joseph

7
@ 프랭크 그것은 큰 따옴표였습니다. 아직도 나는 그것이 아이디어를 이해하는 데 도움이되지 않을 것이라고 생각합니다. 특히 포인터를 처음 접하는 사람에게.
Gulshan

11
이것은 아름다운 이야기입니다 ...하지만 사람들이 포인터를 잘 설명하기보다는 투표로 인해 투표하고 있다고 생각합니다.
Kyralessa

46

다이어그램이 매우 유용하다는 것을 알았습니다. 예:

포인터 다이어그램


이런 종류의 다이어그램은 포인터가 자신의 변수 였지만 다른 객체, 즉 배열이나 문자열의 위치 인 값을 포함하고 있음을 알 수있었습니다. 또한 연필로 할 때 종이나 칠판 / 화이트 보드에서 프로그램을 추적하는 데 사용할 수 있습니다.


4
"포인터"내의 값은 4이거나 배열 인덱스 (또는 메모리 주소)는 0부터 시작해야합니다. 그렇지 않으면 값 3을 보유하는 포인터가 위치 4를 가리키는 방법은 무엇입니까?
MAK

++ 이것은 내가 그것을 설명하는 방법과 정확히 같습니다. 나는 포트란에서 시작했다. Fortran에서 그 당시에는 구조체 배열 대신 병렬 배열을 사용했습니다 ( new 와 같은 것은 없음 ). 하나의 배열에 배열에 "다른 행"의 색인이 포함 된 경우이를 "포인터"라고하며 이는 흥미로 웠습니다. 링크 된리스트와 트리를 만들었습니다.
마이크 던 라비

2
어디에 저장된 내용을 나타내는 그림과 포인터가 가리키는 위치를 나타내는 화살표를 사용하여 가장 잘 설명 된 포인터를 찾습니다.
gablin

32

포인터에 대해 처음 "학습"했을 때, 나는 그것에 대해 약간의 추력을 가졌습니다. 내 대학은 Java를 중심으로 커리큘럼을 중심으로 등록하기 전에 오랫동안 결정을 내렸으므로 데이터 구조 교수가 C에 대해 하나의 강의를하고 포인터로 XOR-List를 구현하도록 요청했을 때 무언가에 들어간 것처럼 느꼈습니다. 방법은 내 머리.

나는 그 정의를 이해했다.

포인터는 변수의 주소를 포함하는 변수입니다

그러나 나는 여전히 개념의 큰 부분을 이해하지 못했습니다. 되돌아 보면 세 가지를 중심으로 생각합니다.

  1. 메모리 위치 정확히 무엇입니까 ? (컴퓨터 조직 수업을 들지 않았을 때)

  2. 어색한 구문 (Soum ... 왜 "int * ip"과 같이 정확하게 정의 되었는가? 그리고 나서 변수를 "ip"로 지칭 하는가?)

  3. 변수를 사용하는 것보다 변수의 주소를 저장하는 것이 얼마나 유익합니까?

K & R 서적을 구매하고 포인터에 대한 이해를 얻을 수있는 모든 문제를 완수하기 전까지는 그렇지 않았습니다. 컴퓨터 조직 수업 (C를 배우기 전에 필요하다고 생각)을 오랫동안 완성했다는 사실 외에도 포인터가 함수, 배열, 구조체에 사용될 수 있다는 사실과 관련이 있습니다. 단지 일반적인 변수의 주소를 저장하는 것이 아니라 유용한 일을하는 것.

그러나 나의 "aha"순간은 K & R이 간단한 포인터를 정의하는 어색한 구문을 설명하는 방식이었습니다. 나는 책을 통틀어 노트를 작성했다 (이것은 나의 이해를 돕기 위해 그 책의 포인트를 내 말로 바꾸어 놓았다).

포인터는 변수에 대한 주소를 포함하는 변수입니다. 포인터는 '*'연산자를 사용하여 정의되고 역 참조됩니다 (포인팅 된 메모리 위치에 저장된 값을 나타냄). 표현은 니모닉입니다.

Ex.: 
   int a;      /* Variable 'a' is an integer */

   int *ip;   /* Variable ip is a pointer and dereferencing it gives an integer.
                 In other words, the expression *ip is an int, so ip is a pointer
                 to an int */

나는 항상 머리에 너무 기초적인 무언가가 생길 때까지 고급 포인터 개념을 완전히 파악할 수 없다고 항상 느꼈습니다. 내가 (* 내가 생각한) "* ip"를 정의한 직후에 "* ip"가 존재하지 않는 이유는 그 임무를 마치고 나에게 끝없이 귀찮게했다. 이것을 마스터하는 것은 함수 포인터와 같은 포인터와 관련된 고급 개념과 다음과 같은 더 복잡한 정의에 필수적입니다.

char (*(x())[])()

대체로 포인터 개념에는 다음이 필요하다고 생각합니다.

  1. 컴퓨터에 메모리를 배치하는 방법과 메모리에 대한 기본적인 이해

  2. 포인터가 얼마나 강력한 지에 대한 지식 (학습을 위해 배우는 또 다른 추상적 인 개념이 아닌 실제 사용).

  3. 구어 적으로 "포인터의 정의"로 알려진 상형 문자 해독

따라서 포인터에 대해 배울 때 적어도 3 개의 "aha"순간이 있어야한다고 생각합니다. 나는 여전히 학생이므로 개념을 배우는 데 여전히 (상대적으로) 신선한 사람의 관점에 감사한다고 생각합니다.


3 "아하!"+1 monents. 그로 킹 포인터는 레이어로 제공됩니다. 내가 실현하기 전에 나는 약 절반 : 포인터에 대한 포인터 이해 오랫동안 점을 "이해"
이진 걱정하는

나는 '포인터를 이해하지 못함'의 매우 큰 부분이 실제로 이상한 C 구문을 사용하고 있다는 점에서 완전히 정확하다고 생각합니다. [생각 : 나는 이런 종류의 문법을 이해하는 것이 얼마나 어려운지 궁금하다. PointerTo<int> a]
Benjol

@Benjol에 동의했습니다. 구문 int* ip이 더 일반적이지 않다는 것에 놀랐습니다 . 이런 형식의 코드를 보았을 때 포인터를 이해하기 시작했습니다. 그런 다음 "ip는 int 포인터 유형입니다."라고 읽을 수 있습니다.
Jacob

19

포인터는 바탕 화면의 응용 프로그램 바로 가기와 비슷합니다. 바로 가기를 삭제해도 대상이 여전히 존재합니다. 바로 가기를 시작하면 대상이 시작됩니다.

나는 항상 바탕 화면에 txt 파일을 만들고 파일에 대한 두 개의 바로 가기를 작성 하여이 작업을 설명합니다. 바로 가기를 복사하고 삭제하면 사람들이 '참조'의 개념을 이해하는 것을 볼 수 있습니다.

그룹이 바로 가기 뒤에있는 기본 사항을 이해하면 원하는대로 포인터 설명을 시작할 수 있습니다. 그들은 아마 그것을 쉽게 이해할 것입니다.


그것은 나쁜 비유가 아닙니다. 문자 그대로 "하드 링크"를 취하는 사람에게 추가해야 할 몇 가지 사항은 디렉토리를 변경하더라도 항상 대상을 가리키며, 개체가 재배치 된 경우에도 포인터는 원래 메모리를 가리 킵니다. "하드 링크"는 대상이 더 이상 존재하지 않을 때 알려주는 댕글 링 포인터 포인터는 NULL로 설정해야합니다.
snmcdonald

하드 링크는 참조 카운트 스마트 포인터
jk와 같습니다.

1
+1. 포인터를 설명하는 가장 실용적인 비유 중 하나입니다. 이 기능은 모든 사람이 가장 일반적으로 사용하므로 학생들은 즉시 아이디어를 얻을 수 있다고 확신합니다.
Karthik Sreenivasan

13

8-10 년 전에 저는 커뮤니티 칼리지에서 "C"과정을 소개했습니다. 이것은 항상 재미있는 주제였습니다. 가장 잘 작동하는 것처럼 보였고, 이것은 동료와 몇 차례 논의한 후에 커피 컵과 손을 사용하는 것이 었습니다.

커피 컵 (또는 배열의 경우 행)의 비유를 변수로 사용했습니다 (무언가를 담을 수 있음). 그런 다음 손을 사용하여 무언가를 잡을 수도 있고 집게 손가락을 펴서 커피 잔을 가리 켰습니다.

가까운 손은 널이었고, (모의 총과 같은) 내 머리를 가리키는 손가락은 매달려있는 포인터였습니다.

그런 다음 몇 가지 데모와 디버거를 통한 트립으로 대부분 클릭했습니다.


3
당신은 이미 나를 혼동했습니다.
kirk.burleson

1
@ 커크, 어떻게? 내가 정리할 수 있는지 보자.
DevSolo

4
++ 이런 것들에 대해 생각하도록 가르치는 것만 큼 좋은 것은 없습니다.
Mike Dunlavey가

대학의 저의 강사 중 한 명이 커피 잔 대신에 학생 (웃음을 더하기 위해 "닐"이었던 학생)을 사용하여 비슷한 일을했습니다. 청중을 손으로 흔드는 것은 무언가를 가리킬 수 있기 때문에 매달려있는 포인터였습니다.
Kaz Dragon

2
매달려있는 포인터는 Neil을 가리키는 것과 비슷합니다. 그러면 당신이 가리키는 곳을 바꾸지 않고 의자를 떠날 수 있습니다. 그런 다음 그 포인터를 따르려고 노력하고 누가 끝났는지에 관계없이 Neil로 찾은 것을 해석합니다.
Jon Purdy

10

"포인터를 어떻게 이해 했습니까"라는 질문을들을 때 정말 걱정이됩니다. 나는 항상 개념이 매우 단순하고 프로그래머에게 큰 힘을 제공하는 언어의 논리적 진화라고 생각했습니다.

나를 걱정하는 것은 포인터의 개념을 이해하는 것이 결코 어렵다는 것입니다. "여러분이 언제 드디어 얻었습니까?"

나는 실제로 그것을 얻습니까? 어쩌면 내가 한 적이 없는가?

어쩌면 개념이 까다로운 것으로 보이는 이유는, 아직 접하지 않은 모든 사람들에게 포인터가 너무 어렵다는 것을 계속 알려주기 때문입니다. 여기에 당신이 배울 수있는 백 가지 방법이 있습니까?

그 아이디어를 버리는 것, 물론 개인적으로 나는 좋은 다이어그램을 좋아하고 Steve Gibson은 항상 무언가를 설명하는 환상적인 일을합니다 !


흥미 롭습니다 ... 당시에 어떤 언어를 사용하셨습니까? C 구문은 많은 사람들을 여행한다고 생각합니다. 집회를 먼저 안다면 한 가지 이유가 있습니다. [BTW,이 투표에 투표하고 싶지만 오늘은 상한선에 도달했습니다.]
Macneil

흥미롭게도, 파이썬 (및 대학의 Java)에서 일하면서 오랫동안 "위험한"포인터에 대한 지식이 없었습니다. 그런 다음 C ++을 선택한 언어로 사용하는 "객체 지향 메소드"모듈을 사용하여 바로 그 언어를 사용했습니다.
Marcus Whybrow

또한 프로그램이 메모리에 어떻게 표현되는지 이해하는 것이 확실히 도움이 될 수 있다고 생각하지만 포인터가 왜 언어에 유용한 추가 요소인지 이해하는 것이 가장 효과적인 각도라고 생각합니다. 원래 디자이너로 프로세스.
Marcus Whybrow

+1 사람들이 왜 포인터가 어렵다고 생각하는지 모르겠습니다.
ggambett

예, 포인터는 항상 매우 간단하고 유용하여 그에 대해 "어려운"것이 있다고 생각할 수 없습니다. 모든 코스의 교사가 "이것은 조금 까다 롭습니다"라고 말할 때 나는 그것을 싫어합니다. 그 빌어 먹을 물건을 가르치고 학생들이 까다로운 생각인지 스스로 결정하게하십시오.
Jon Purdy

7

C에서 포인터에 대해 큰 문제는 없었지만 어셈블러를 먼저 배워야했기 때문일 수 있습니다. 실제로 주소를 더 이상 관리하지 않아도되는 것은 실제로 안도감이었습니다. 따라서 대답은 (이것이 가르치고 있다고 가정 할 때) 학생들에게 에뮬레이트 된 어셈블리 언어를 제공하는 것입니다. 그들은 보다 더 정교한 아무것도 작성하는 과정에서 그것을 알아낼 "안녕하세요, 세상을."


유추를 사용하지 않고보다 원시적 인 추상화를 적용하면 +1입니다.
익명 유형

고등학교에서 컴퓨터 연구의 한 단위는 성냥갑 컴퓨터 를 연구하는 데 전념했습니다. 성냥갑 컴퓨터 는 실제 컴퓨터를 건드 리거나 관련시키지 않고 칠판에서 배울 수 있습니다.
rwong

@Larry Coleman, 어셈블리 !!!!!!!!!!! C 전에 먼저 시도하고 싶습니다. 학습을 시작할 위치를 알려주십시오. 무료 전자 책, 무료 PDF? IDE? 부디!!!!!!!!!!!!!!!!!!!
Spacez Ly Wang

7

포인터는 값이 다른 변수의 메모리 주소 인 변수입니다.


우아하고 왜 더 복잡하게 만듭니다.
Bjarke Freund-Hansen

포인터가 즉시 직관적이고 유용하지 않으면 잘못 설명 된 것입니다.
Jon Purdy

6

포인터에 대해 어떻게 실제로 배웠습니까? 대학 신입생 간단한 컴파일러 작성.

평신도의 용어로 포인터를 설명하는 방법? 인덱스 카드에 저장된 라이브러리 카탈로그의 (날짜?) 유추를 좋아합니다. 각 카드 ( "포인터")에는 일부 책 ( "데이터")이있는 위치에 대한 정보가 있지만 실제로는 책 자체를 포함하지는 않습니다. 카드를 수정하면 ( "포인터 산술") 카드가 가리키는 책을 변경하고 책 자체에 영향을주지 않으면됩니다. 주소를 망치지 않도록주의하거나 존재하지 않는 책을 가리킬 수 있습니다 또는 잘못된 라이브러리. 그러나 카드의 "주소"를 따라 라이브러리의 올바른 부분 ( "포인터 참조 해제")으로 이동하면 책 자체를 보거나 수정할 수 있습니다.


내가 정확히 설명했던 CS 과정의 기억에 +1
Gary Rowe

카드가 실제로 책의 위치를 말하지 않기 때문에 그것은 좋은 방법이지만 다소 오해의 소지 가 있습니다. 여전히 운동화 중심 검색 알고리즘을 실행해야합니다. 아마도 이것은 데이터베이스를 더 잘 모델링 할 수 있습니다-키 (통화 번호)로 저장된 객체를 참조하십시오.
DarenW

+1 유추는 Barfieldmv가 설명한 것과 같은 개념을 유지 하지만보다 실제적인 접근 방식입니다.
Karthik Sreenivasan

5

포인터를 배우려는 사람이 정상적인 변수가 무엇인지, C에서 어떻게 작동하는지 알고 있다고 가정합니다. 이제 일부 속성으로 포인터를 정의 해 보겠습니다.

  • 또한 변수이지만 특성이 다릅니다. 가변 공간에 두 개의 레이어가 있다고 가정합니다. 다른 유형의 일반 변수는 상위 계층에 있고 하위 계층에 포인터가 있습니다. 이 그림처럼

    대체 텍스트

  • '포인터'라는 이름에서 알 수 있듯이 포인터는 무언가를 가리킬 수 있습니다. 손가락처럼 어떤 물체를 가리킬 수 있습니다. 그들이 지적하는 것은 무엇입니까? 이것들은 정상적인 변수입니다. 간단히 말해 "포인터는 일반 변수를 가리 킵니다".

  • 일반 변수와 마찬가지로 포인터도 int, char 또는 float와 같은 유형입니다. 특정 유형의 포인터는 동일한 유형의 변수 만 가리킬 수 있습니다.
  • 포인터는 하나의 변수를 가리키고 나중에 동일한 포인터는 다른 변수를 가리킬 수 있습니다. 유형 만 같아야합니다. 따라서 포인터와 일부 변수의 연관은 영구적이지 않으며 변경할 수 있습니다.
  • 그렇다면 포인터는 어떻게 선언됩니까? 일반 변수와 거의 같습니다. 이름 앞에 별표 ( *) 를 붙여야합니다 . 처럼-

    int *pointer;
    
  • 그런 다음 포인터는 변수와 어떻게 연관되어 있습니까? &이 문장처럼 변수 앞에 연산자 사용 하기

    pointer = &variable;
    
  • 변수를 가리키는 포인터는 어떻게 사용됩니까? 이름 앞에 별표 ( *) 를 붙여서 수행합니다 . 그런 다음 현재 가리키는 변수 대신 사용할 수 있습니다.

    *pointer = var1 + var2;
    

    대신에

    variable = var1 + var2;
    
  • 이제 몇 가지 코드로 포인터를 사용하십시오. 포인터의 이러한 특성에 익숙해 지십시오. 지금까지 우리는 포인터가하는 일에 대해 이야기하고 있습니다. 문제가 없으면 포인터가 변수를 가리키는 방법과 정상적인 산술 연산이 적용되는 경우 어떻게 반응하는지 연구하십시오. 그런 다음 포인터와 배열 사이의 관계 및 포인터에 대한 포인터로 이동하십시오.

이것이 포인터 학습에 관해 제안 할 전부입니다.


"먼저 무엇을하고 어떻게하는지"프로세스를 따르고 싶었습니다. 추출!
Gulshan

5

질문의 수정 된 요구 사항을 지원하기 위해 편집

"포스트 포인터"이해 (내가 정확하게 기억한다면)에 대한 나의 길은 이렇게 갔다. BBC Micro와 여전히 관련이 있었을 때부터 어셈블리 프로그래밍에 대한 간단한 경험이 있었으므로 메모리 개념을 여러 상자로 사용했습니다 (아래 참조). 이것은 배열을 사용하여 강화되었습니다. 그러나 나는 C의 세계로 가고 있었고 문자열을 다루어야했고 그것은 포인터를 의미했습니다. BASIC에서 이것은 사소한 것이었고 어셈블러에서는 결코 그들과 함께 일할 필요가 없었으며 이제는 고전적인 C에서는 모든 포인터와 물건입니다. 아, 그러나 다음과 같이 (null로 끝나는) 문자열을 가진 배열로 다시 되돌릴 수 있습니다.

char s[] = "Hello, world!";
printf("%s",s);

모든 것이 좋고 훌륭합니다. 마지막으로 문자가있는 배열 (내 작은 세계에서 문자 당 8 비트)은 끝 부분에 0 문자가있는 곳입니다. printf는 그 배열을 가져 와서 그것을 인쇄합니다. 그러나이 문자열을 함수에 전달하려면 어떻게해야합니까?

void print_str(char* p) {
  printf("%s",p);
}

매뉴얼에 나와있는 내용이 무엇입니까? 흠, char *는 "char에 대한 포인터"를 의미합니다. 알았어 .. 날 잃었 어 그런 다음 char *가 p를 s [0]과 동일하게 만듭니다. 좋아, 나는 그것을 사용할 수 있지만, 나는 여전히 포인터가 무엇인지 잔가지로 만들지 않았다. 내 말은,이 중 하나를 사용하여 데이터를 어떻게 설정합니까? 다시 매뉴얼로 ...

char* p = "Hello World!";

위의 내용을 쓸 때 "문자에 대한 포인터를 선언 하고이 문자 배열과 동일하게 설정하십시오"라고 스스로에게 말하고 있습니다. 어떻게 든 그 포인터는 배열의 필요성을 없애줍니다. 컴파일러가 변경을 위해 나를 위해 몇 가지 일을하고 있다고 생각합니다. 그렇다면이 포인터로 어떻게 배열을 변경할 수 있습니까? 배열 버전을 사용할 수 있음을 알고 있습니다

 s[2] = 'L'; 

"포인터 말하기"와 동등한 것은 무엇입니까? 그 설명서를 다시 벗어 ...

*(p+2) = 'L';

나는 * 단순히 "메모리 주소의 내용"을 의미하고 있다고 가정 (p+2)이다 s[2]. 그것은 포인터 p가 ... 그냥 ... 주소 ... bong!

깨달음의 소리가 있습니다. 나는 갑자기 포인터를 움켜 쥐었다 (오래 전에는, 우리는 오래된 타이머가 나중에 "그루밍"하지 않았다). 그것은 단지 간접적 인 것이었다.


기발한:

좋아, 내 2c 가치는 :

기억이 많은 상자라고 상상해보십시오. 각 상자에는 측면에 번호가 있습니다 (주소). 각 상자에는 숫자 (내용)가 들어 있습니다. 당신은 두 가지 방법으로이 상자와 함께 작업 할 수 있습니다 변수 (I 상자 N의 내용을 원하는), 포인터 (I 상자의 내용을 원하는 상자 N에 무엇이든을 ). 포인터는 단순히 간접적입니다.

그리고 당신이 알아야 할 모든 것을 포괄하는 큰 대답을 위해 이것을 읽으십시오 .


++ 그것은 내가 주제를 가르치는 방식과 거의 비슷합니다.
Mike Dunlavey가

OP 요구 사항을 지원하도록 편집 된 기사
게리 로우

문자열 끝에 여분의 NUL 문자를 추가 한 어떤 매뉴얼을 사용 했습니까?
Rob Gilliam

@raimesh 아주 오래된 것입니다 (1991 년경). 어느 것을 기억하지 못합니다.
게리 로우

1991? C 언어 매뉴얼은 오래되지 않았습니다 .K & R의 제 1 판은 1978 년에 출판되었습니다! 방금 문자열 상수의 끝에 \ 0을 넣어야한다고 제안하는 매뉴얼이 있다는 것에 흥미를 느꼈습니다. (실제로 다시 살펴보면, \ n을
쓰려고

4

작은 나무 블록을 가져옵니다.

한쪽에는 금속 고리를, 다른쪽에는 금속 고리를 추가하십시오.

당신은 지금 당신이 재생할 수있는 것들에 링크 목록을 할 수 있습니다.

이 실제 소품으로 설명해보십시오. 나는 종종 1 학년 (신입생) 학생들에게 포인터를 가르 칠 때 이런 일이 있기를 바랐습니다.

작은 금속 고리는 포인터, 나무 블록이 지적한 것입니다.

나는 블록을 가지고 노는 후에 그것을 얻지 못하게 누군가를 정의합니다.


4

나는 모든 보풀을 제거하고 포인터를 마법의 실체가 아닌 다른 변수로 취급하기 시작했을 때 (내 인생이 더 쉬워졌습니다 (오래 11 학년)).

  1. 포인터는 다른 변수의 주소 (또는 모든 주소)를 저장하는 변수입니다.
  2. *는 포인터 변수에 저장된 메모리 위치에서 값을 얻는 데 사용됩니다.
  3. & 연산자는 메모리 위치의 주소를 제공합니다.

나머지는 구문 설탕과 상식입니다. 그냥 링크를 사용하여 포인터를 사용하여 간단한 C 프로그램을 작성하십시오.


2
  1. 포인터는 인덱스를 배열로 일반화 한 것으로 생각할 수 있습니다.
    • 큰 어레이는 겹치지 않는 가변 크기의 작은 어레이로 잘릴 수 있습니다. 이제이 작은 배열은 일반적으로 배열이라고 생각합니다. 더 큰 것은 컴퓨터의 전체 메모리 공간입니다. 작은 배열을 잘라내는 과정을 메모리 할당이라고합니다.
  2. 일부 포인터에 의해 서로 연결된 일련의 구조는 유 방향 그래프 로 생각할 수 있습니다 .
    • 각 정점은 일부 값을 보유 할 수있는 변수입니다.
    • 일부 변수는 포인터이며 각 포인터는 정확히 다른 하나의 바깥 쪽 모서리를 가질 수 있습니다.
    • 포인터가 아닌 변수는 나가는 모서리가 없습니다. 그들은 들어오는 가장자리 수에 제한이 없습니다.

2

내 포인터 aha-moment 주위의 상황을 기억할 수는 없지만 c 스타일 배열에 대한 나의 이해와 관련하여 소급하여 기억을 개조했습니다. (예 : arr[3]와 동일 *(arr+3))

어떤 이유로 포인터 포인터가 발생할 때마다 포인터를 배열로 보는 것이 매우 도움이됩니다.


2

@Gary Rowe는 기본적으로 올바른 모델을 소개했습니다. 주소 (숫자)가있는 상자 세트로서의 메모리. 각 상자에는 값 (숫자)이 저장됩니다.

포인터의 아이디어는 한 상자의 값을 다른 상자의 주소로 해석하는 것입니다. 이 값은 특정 상자 를 참조 하는 데 사용 되므로 reference 라고합니다 . 따라서 역 참조참조 된 상자를 여는 과정입니다.

경우는 v변수 (상자), 다음 문이다

  • v값 의미 v, 즉 줘 상자에 무엇
  • *v의 값을 역 참조 함을 의미합니다 v. 즉, 상자에있는 값을v
  • &vv, 상자에 주소를 알려주십시오.

포인터를 완전히 다른 것으로 소개하려는 목적을 서버에 포함시키지 않는다고 생각합니다. 내가 어렸을 때 이해하기 어려운 개념이었습니다. 그것은 항상 내가 정말로 이해하지 못한 어두운 마술처럼 보였고, 많은 특수 문자가 필요했습니다. 내가 처음으로 이해 한 것은 포인터 산술이없는 언어에서 이중 간접을 사용하여 작은 게임을 썼을 때였습니다. 그것은 나를 깨달았습니다.

포인터는 해석의 문제입니다. 설명이 훨씬 쉬워졌습니다. 그리고 10 개의 변수의 메모리를 가진 간단한 예제를 보여 주면 포인터 산술은 매우 간단하고 직관적 인 연산입니다.


2

내가 실제로 낀 설명은 다음과 같습니다.

땅 위에 다른 집들이있는 도시 격자를 생각해보십시오. 당신의 손에는 종이 한 장이 있습니다. 종이에 당신이 쓴 :


데이비드의 집,

112 그렇게 거리.


종이 (포인터 변수)에는 다윗의 집을 가리키는 주소가 들어 있습니다 . 친구에게 David의 멋진 집을 보라고 말하고 싶을 때 실제 2 층 건물을 우편으로 보내는 것보다 종이 그림을 집에 대한 참조로 사용하는 것이 훨씬 쉽습니다.

실제 포인터와 마찬가지로 용지의 주소를 따를 때 문제가 발생할 수 있습니다. 다윗은 움직일 수 있었으며 그곳에 도착하면 땅에 큰 구멍이 생겼습니다. 이 경우 David가 이동하거나 최소한 새 주소로 변경했을 때 종이의 주소를 지우는 것이 좋습니다. 또한 주소로 가서 친구 David의 거실이라고 생각하는 것을 입력 할 수 있지만 이번에는 완전한 낯선 사람 수영장에있게됩니다. 다른 사람이 당신이 가진 주소의 공간을 완전히 다른 것으로 사용했습니다.


2

포인터를 설명하려면 먼저 메모리를 설명해야합니다. 나는 보통 행과 열이있는 그래프 용지 / 제곱 용지를 사용하여 그렇게합니다. "학생"이 메모리를 이해하면 주소가 무엇인지 이해할 수 있습니다. 주소가 있으면 포인터가 있습니다.

이 추상화로 놀 수 있습니다. 예를 들어 한 사각형의 주소 (숫자)를 다른 사각형에 씁니다. 이제 포인터 사각형에서 대상 사각형으로 화살표를 그립니다. 이제 포인터를 덮어 쓰고 (예 : 증분) 화살표를 조정하십시오. 다른 광장에 주소를 쓰고 학생이 화살표를 그리도록하십시오.

다음 단계 : 포인터와 같은 특정 사각형에 이름을 지정하십시오. 이제 역 참조를 설명 할 수 있습니다. 그게 다야.


2
실제로 전자를 사용하는 컴퓨터에 손을 넣기 전에 사용한 "컴퓨터"를 생각 나게합니다. 골판지 "CARDIAC"이라고합니다. 말 그대로 번호가 매겨진 상자에 숫자를 쓰면 다른 번호가 매겨진 상자에서 숫자를 얻을 수 있습니다. 그것은 이었다 교육과 나는 문제가 실제 마이크로 프로세서에 대한 포인터를 이해 없었어요.
DarenW

2

어쩌면 그것은 나뿐이지만 나는 유추와 잘 어울립니다. 따라서 다른 사람 (다른 기능 / 클래스), "바"를 갖고 싶은 친구 (기능 / 클래스) "Foo"가 있다고하자. "Foo"는 "Bar"를 보러 갈 수 있지만 편리하지는 않습니다. 모든 존재 (인스턴스)를 움직입니다. 그러나 "Foo"는 전화 번호 (포인터)를 "Bar"로 보낼 수 있습니다. 이렇게하면 어디에 있든지 "Foo"는 사용자를 찾을 필요없이 연락하는 방법을 알고 있습니다.

그리고 "Bar"가 당신과 연락을주고 싶어하는 지인 "Baz"를 가지고 있다고합시다. 그러나 귀하는 귀하의 전화 번호를 보호하고 모든 사람이 "바즈"를 "바"(포인터로 전화)로 전화를 걸면 통화를 다른 사람에게 전달할 수 있습니다. 그리고 "Baz"의 친구들과 친구들의 체인이 계속해서 내려오고 있습니다.


2

포인터는 만드는 방법 은 어셈블리 언어 및 / 또는 컴퓨터 아키텍처를 연구 한 경우 더 의미. C 클래스를 가르치면 메모리 모델과 프로세서가 실제로 실행하는 명령의 종류를 설명하기 위해 몇 주 동안 아키텍처를 시작할 것이라고 생각합니다.


물론. 레지스터를 처리하고 즉각적인 값 및 간접 주소 지정과 같은 것을 이해하면 포인터의 전체 개념이 직관적입니다. C의 첫 번째 줄을 작성하기 전에 6502 어셈블리와 68K 어셈블리를 배웠으므로 포인터를 소개 할 때 컴파일러의 (중간) 어셈블리를 보았으며 정확히 예상대로였습니다.
Radian

2

내 "아하!" 이 튜토리얼에서 순간이왔다 :

C의 포인터와 배열에 대한 튜토리얼

정확히 말하면이 장에서는 다음 과 같습니다. 3 장 : 포인터와 문자열

더 정확하게 말하자면, 다음 문장과 함께 제공됩니다.

puts ()에 전달 된 매개 변수는 포인터, 즉 포인터의 값입니다 (C의 모든 매개 변수가 값으로 전달되므로). 포인터의 값은 포인터가 가리키는 주소 또는 간단히 주소입니다. .

내가 그것을 읽을 때 구름이 갈라지고 천사들이 나팔을 불었다.

내가보기에 읽은 모든 C 튜토리얼이나 책은 C가 가치 나 참조로 사악한 거짓말을 할 수 있다고 주장했다. 진실은 C가 항상 가치를 지니지 만 때로는 전달 된 가치가 주소가된다는 것입니다. 메서드 내에서 복사본은 전달 된 int로 만들어지는 것처럼 해당 주소로 만들어집니다. 포인터는 가리키는 값으로 만들어 지지 않습니다 . 따라서 메소드 내에서 포인터를 사용하면 원래 값에 액세스하여 변경할 수 있습니다.

저는 C 프로그래머가되지 않았지만 .NET 프로그래머가되었습니다. 객체와 객체 참조는 같은 방식으로 작동합니다. 객체에 대한 참조는 값에 의해 전달되므로 복사되므로 객체 자체는 복사되지 않습니다. 나는 포인터를 배우지 않았기 때문에 이것을 이해하지 못하는 많은 프로그래머들을 위해 일했습니다.


1

비결은 파이프의 그림이 파이프 가 아닌 것처럼 사물의 위치와 사물 자체가 동일하지 않다는 것을 설명하는 것 입니다. 물건을 움직이면 그 위치가 바뀝니다. 위치가 남아 있고 다른 것을 넣을 수 있습니다.


1

포인터는 유용한 것이 어디에 있는지 알려주는 스티커 메모입니다. 그것은 물건의 위치를 ​​포함하고 물건이 얼마나 큰지 알려줍니다 (어쨌든 C에서). 따라서 이중 포인터는 "냉장고에 6 개의 팩이 있습니다"라는 스티커 메모와 같습니다. 콜라 나 버드 와이저인지 알아 내기 위해 실제로 6 팩을 가져 가야합니다.


1

주어진 코드 :

int v=42; // 간단한 변수 선언 및 초기화

int *p = &v; // 변수 v에 점 p 만들기

위 코드에 대해 다음과 같이 말할 수 있습니다.

int * p // "int pointer p"... 이것은 int 유형의 변수에 대한 포인터를 선언하는 방법입니다

*p // "p가 가리키는"... 이것은 p가 가리키는 데이터이며 v와 같습니다.

&v // "변수 v의 주소"... p의 리터럴 값을 나타냅니다.


1

http://cslibrary.stanford.edu/

이 사이트에는 포인터 및 메모리 관리 학습을위한 훌륭한 자습서가 있습니다.

나는 당신이 사이트에 주어진 포인터 기본 사항, 포인터 및 메모리를 안내하도록 제안합니다. 포인터 개념을 더욱 강화하기 위해 링크에 제공된 링크 된 목록 문제를 볼 수도 있습니다.


1

포인터를 설명하는 열쇠는 설명하는 사람들이 이미 메모리 개념을 이해하고 있는지 확인하는 것입니다. 메모리가 거대한 배열로 존재한다고 생각하고 인덱스 위치로 배열의 모든 위치에 액세스 할 수 있다는 것을 이해하면 충분하다는 것을 실제로 이해하면 좋을 것입니다.

다음 단계는 전체 메모리를 복사하는 대신 인덱스 위치를 전달한다는 개념을 갖는 것이 대부분의 사람들에게 의미가 있습니다. 그리고 그것은 대부분의 사람들이 왜 포인터가 유용한 지 이해할 수 있도록 충분합니다.

포인터를 이해하기위한 마지막 단계는 모든 데이터가 저장되는 인덱스 위치를 저장하는 메소드의 메모리 인덱스 위치를 매개 변수로 전달하는 방법을 설명하는 것입니다. 나는 이것이 일부 사람들이 대처하기에는 너무 멀다는 것을 알았습니다.

누군가가 이러한 기본 단계를 파악한 후에는 실제 데이터 개체를 찾기 위해 주소를 몇 번 봐야하는지 추적하는 한 포인터를 무한정 연결할 수 있다는 것을 쉽게 이해할 수 있습니다.

누군가 포인터를 잡으면 힙 메모리와 스택 메모리의 차이점과 스택 메모리에 대한 포인터가 메소드 외부로 전달 될 때 위험한 이유는 빠르게 파악해야합니다.


0

나는 도서관에서 구할 수있는 몇 가지 프로그래밍 / 컴퓨터 관련 서적 중 하나 였기 때문에 순수하게 읽은 책 "C 퍼즐"또는 이와 유사한 것을 기억한다. C에 대한 나의 이해는 초보적이었다. 그것은 당신에게 C Expresison을 던졌고 그것을 설명하기 위해 점점 더 복잡해졌습니다.


0

내가 대학에 있었을 때, 교수님은 메모리 위치 (어레이처럼 나타남)에 화살표가있는 점을 별도의 변수로 묘사하는 정말 깔끔한 파워 포인트 슬라이드를 가지고 있었고 우리가 Linked Lists를 할 때, 그는 단계를 밟을 것입니다 -화살표가 변경 될 때, 포인터가 역 참조 될 때 등을 보여주는, 몇 분 안에 그것을 이해할 수 없었습니다. 개념 자체는 정말 쉽지만 실제 프로그램에 적용하거나 실제 프로그램에 적용하려면 더 많은 연습이 필요합니다.


0

그렇게하기 전에 프로그래밍 할 때 "모든 것이 메모리를 사용"하고 메모리에서 (정적) 변수 할당을 설명합니다. 또한 메모리 주소가 무엇인지, 메모리 공간, 메모리 주소 및 변수 간의 관계에 대해 설명합니다.

마지막으로, 0 o ""와 같은 빈 값을 갖는 메모리 주소를 저장하는 특수 데이터 유형이 있음을 설명 할 때까지 정수 데이터 유형 및 변수, 문자열 데이터 유형 및 변수 등이 있다고 설명합니다. null 이라고 합니다.

마지막으로 포인터 사용을 통해 동적으로 할당 된 변수입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.