:: 게시판
:: 이전 게시판
|
- PGR21 관련된 질문 및 건의는 [건의 게시판]을 이용바랍니다.
- (2013년 3월 이전) 오래된 질문글은 [이전 질문 게시판]에 있습니다. 통합 규정을 준수해 주십시오. (2015.12.25.)
통합규정 1.3 이용안내 인용"Pgr은 '명문화된 삭제규정'이 반드시 필요하지 않은 분을 환영합니다.법 없이도 사는 사람, 남에게 상처를 주지 않으면서 같이 이야기 나눌 수 있는 분이면 좋겠습니다."
16/09/19 00:50
malloc(sizeof(list))
이 명령이 list의 크기만큼 메모리를 할당하라는 얘기라 특정 형을 정의한것과 같다고 볼 수 있겠죠 malloc의 return이 void형 포인터라 student에 넣기 위해 student의 자료형인 list * (list형 포인터) 로 만들어줘야 한다고 알고 있습니다.
16/09/19 01:15
어차피 메모리에는 바이트, 비트 단위로 여러 값이 나열되어 있을 뿐이니까요. 구조체나 변수 같은 개념은 프로그래밍 중인 프로그래머와 컴파일러가 고려하는거고, 실제 프로그램이 동작하면서는 별로 상관이 없습니다.
구조체 크기 만큼의 빈 공간이 있고, 그 공간을 구조체 처럼 사용하는거죠.
16/09/19 01:37
포인터는 본체를 가르치는 키입니다
malloc은 구조체에 필요한만큼 공간을 할당한다는 의미입니다. 말록으로 할당한 공간과 그것을 가리키는 키를 생성했으니까 말씀하신기 맞습니다
16/09/19 03:40
C 언어를 배울 때 장벽인 개념이 포인터지요.
예전에 학생들을 가르칠 땐 이렇게 가르치곤 했습니다. 내가 집을 구매한다고 할 때 포인터와 포인터 캐스팅의 본체인 malloc 은 다음과 같은 역할을 합니다. 1. 포인터 = 구매할 집의 행정지 주소 2. malloc 를 통한 메모리 공간 확보 = 실제 거주하는 집 건물 포인터를 이해하는 가장 간단한 방법은, 메모리라는 하드웨어의 구조를 이해하는 것으로부터 시작합니다. - 메모리는 엄청나게 거대한 저장공간의 block 으로 이뤄져 있다고 연상합니다. - 그리고 c 언어에서 포인터는 각 block 의 [위치] 를 이야기 합니다. - 포인터는 메모리의 해당 위치에 무엇이 있는가를 알 수 없습니다. 그저 무조건 [메모리의 특정 block] 만을 가르킵니다. - 그리고 포인터 주소를 캐스팅하여 그 공간에 위치하는 것이 [무엇인가] 를 컴파일러에게 알려줍니다. - 하지만 포인터에게 가르킨 주소에 그 [무엇인가] 가 존재하지 않고 다른 녀석이 있다면 프로그램은 오류를 뿜습니다. - 그래서 포인터에게 주소를 가르키기전에, 그 [무엇] 을 malloc 를 통해 할당하고, 거기엔 [무엇] 이 있을 것임을 미리 결정해둡니다. - 마지막으로 malloc 으로 만들어둔 [무엇] 의 주소를 포인터에게 가르켜주며 [무엇] 이 해당 block 에 있음을 캐스팅으로 전달합니다. 이 과정만 그냥 떠올려두시면 쉽습니다. 1차원 포인터를 이해하시고 나면, 2,3차원 포인터도 큰 문제 없이 넘어가실 수 있습니다 ^^
16/09/19 18:07
구조체는 일반적인 정의든, 포인터변수에 메모리 할당후 캐스팅해서 시작주소를 기록하든 '무엇'에 접근하는 방법이 다를 뿐인건가요?
16/09/19 05:06
사실 별로 좋은 방식은 아니지요.
구조체가 메모리상에서 관리되는 방식에 따라 달라질 수 있는데, C에서는 메모리상에 순차적으로 위치하는 저장공간이라고 가정하고 있는 것이지요. C++에서는 student = new list; 와 같이 좀더 나은 방식이 사용됩니다.
16/09/19 10:52
여기서 궁금한게 단지 메모리를 할당해서 반환되는 포인터를 넣었을 뿐인데 그게 구조체가 생성되는걸로 볼수 있는건가요? (list *)로 캐스팅하고 student로 넣는 것만으로도 어떻게 구조체가 생성되는지 이해가 되지 않습니다..
=> 구조체가 생성된다기 보다는 구조체의 크기만큼 할당한 메모리를 프로그래머 맘대로 쓰겠다 입니다. 할당해서 반환되는 메모리 영역을 프로그래머가 list 로 생각하고 쓰는것입니다. 구조체의 크기만 동일하면 다른 포인터로 변환해서 쓸 수 있습니다. c언어는 실제 할당한 메모리 영역에 프로그래머가 변환해서 쓰려고 하는 구조체가 실제로 들어있는지 전혀 상관하지 않습니다. 다만 캐스트하는 포인터의 사이즈를 계산해서 그 만큼만 프로그래머가 write 할 수 있도록 해 줍니다. 그래서 잘못될 여지가 많습니다. 메모리 사이즈만 같은 아이로 바꿔서 이것저것 해봐도 실제로 write가 일어나기 전까지는 합당한 문장이니까요. c++나 java는 실제 메모리 영역에 할당된 오브젝트가 프로그래머가 캐스트 하려는 오브젝트와 같은지 체크합니다. 예를 들어 list 포인터는 실제 list object 가 있거나 list object의 자식들만 point 할 수 있습니다.
16/09/20 00:09
그렇습니다.
1. malloc(sizeof(list)) 이 문장이 실행되면 list 구조체의 크기만큼의 공간이 메모리 어딘가에 할당됩니다. 이 공간은 예약되어 있고 사이즈는 char 1 바이트 , int 4 바이트, 포인터 8 바이트 ( 64비트 ) 합해서 13바이트가 할당되어야 합니다. (사실은 4바이트 단위로 할당하므로 3바이트를 패딩하여 16바이트가 할당됩니다.) 이 할당된 공간은 꼭 list 구조체만 쓸수 있는것이 아닙니다. 예를 들어 4바이트 int 네 개가 들어있는 integer array 도 사이즈가 같으므로 충분히 쓸 수 있습니다. int* pIntArray = (int *)malloc(sizeof(list)); 이렇게 해도 아무 문제 없다는 이야기입니다. 다만 실제 16바이트가 할당되었으므로 5번째 integer를 읽고 쓴다던가 하면 내가 할당한 곳이 아니므로 ( 다른 사람이 사용하고 있는 공간일 수 있습니다) 프로그램이 어떻게 행동할지 아무도 모릅니다. segmentation fault 가 날 수 도 있고 undefined behavior 가 일어날 수 있습니다. 2. student = (list *)malloc(sizeof(list)); 이 문장이 실행되면 메모리에 할당한 16바이트에 list 구조체의 한 인스턴스가 들어 있다고 말해주는 것입니다. 그래서 student->name 이라고 하면 컴파일러가 어디서 얼만큼 읽어와야 하는지 알 수 있습니다. student->grade 는 할당된 메모리에서 4바이트 더 지나서 읽어야 한다는 것을 구조체를 보고 컴파일러가 알 수 있습니다.
16/09/19 14:01
사실 구조체만큼의 메모리 그것이 구조체란 인스턴스의 실체입니다. 즉 그만큼 크기의 메모리를 잡아서 구조체타입으로 캐스팅해서 쓰는게 정상적인 오퍼레이션이 되는 것이죠. 다만 차이가 있다면 구조체를 지역변수, 전역 변수로 할당하는 것과 메모리 영역만 다른 것이죠.
malloc은 힙영역에 생성되는 것이고 지역변수로 선언했다면 지역변수의 스택 영역, 전역 변수라면 코드메모리 영역에 생성되는 것이 차이입니다. 사실 포인터의 타입이란게 거창한 것이 아닙니다. 포인터는 주소값이라 플랫폼에 따라 32비트 64비트인 값을 가지고 있을 뿐입니다. 그것에 어떤 타입의 포인터든 그 사실은 변하지 않습니다. 구조체의 포인터든 배열의 포인터든 보이드포인터든 그냥 숫자값이 들어있는 것이죠. 그런데 그냥 그렇게 쓰면 사람들이 햇갈리니까 그 주소의 실제로 무엇이 있냐를 타입으로 나타내는 것입니다. 저 주소에는 4층짜리빌라(int)가 있어 15층짜리 배열이 있어 이렇게요. 그래야 그 포인터의 있는 무언가를 사용하고자할때 혼동이 없으니까요. 실제로 4층짜리 빌라밖에 없는데 5층에 접근한다던가 이러면 문제가 생기니까 int라는 것을 가리키는 포인터다 int* 라고 선언을 하는 것이에요. 사실 C++, 자바에서 등장하는 객체를 이용한 상속같은 것도 실제로 동작은 포인터로 동작 하는 것이에요.
16/09/19 20:07
선언과 할당의 차이를 이해하셔야 될 것 같네요.
선언만 해서는 이용할 수 없어요. 할당을 하셔야 합니다. C에서는 malloc C++에서는 new 로... 열혈강의 C포인터랑 C++ 추천 드립니다. 특히 C포인터는 사다리 그림 다 그려가면서 익혀보시길... 포인터와 배열의 차이점과 유사점을 익히시고, 타고급언어에서 보기 힘든 포인터의 매력에 흠뻑 빠지실거에요!
|