포인터와 배열
: 배열 변수명에는 '배열' 이라는 의미보다 '포인터' 라는 의미를 갖고 있다
배열 변수명의 의미
: 정확히 말하자면 다르지만 배열 변수명은 '포인터' 라고 볼 수 있다.
배열 인덱스를 집어넣어 값을 가져오는 [] 대괄호는 해당 주소값에서 몇번째 뒤쪽의 값을 가져오느냐 라는 의미를 갖고있다
배열도 근본은 포인터랑 같다
#include "prc.hpp" int main(){ int myArray[100]; // myArray 부분은 주소를 갖고있다 int* pMyArray = myArray; // pMyArray 라는 배열 변수에 주소를 집어넣어 줄 수가 있다 pMyArray[0] = 100; pMyArray[1] = 200; pMyArray[2] = 300; printf("%d\n", myArray[0]); // pMyArray[0] 을 출력해도 같은 값을 출력 return 0; } |
포인터 값을 가져오는 것의 의미
(*pv) 의 형태로 가져온다는 것은 해당 주소값의 값을 가져온다는 것
pv[0] 의 형태로 가져온다는 것은 해당 주소값에서 0번째 위치의 값을 가져온다는 것
즉 결론적으로 (*pv) 라는 표현과 pv[0]이라는 표현은 동일한 표현임
대괄호를 입력하고 숫자를 입력하는 것으로 해당 포인터를 '배열과 같은 방법'으로 활용할 수 있다
*변수명과 같은 방법으로 값을 가져올 수 있지만 변수명[0] 과 같은 방법으로도 값을 가져올 수 있다
#include "prc.hpp" int main(){ int v1; int* pv1 = &v1; printf("%d\n", pv1[0]); // 주소값을 따라가서 그 주소값의 0번째 index에 있는 값을 가져오라는 의미 printf("%d\n", *pv1); // 위의 코드랑 같은 출력값 return 0; } |
문자열 포인터
: 문자열을 포인터로 사용할 때에는 const char*를 활용한다
단순히 char*를 사용할 때는 동적할당 문자열을 사용할 때 사용하며
const char*를 사용하는 경우는 우리가 실제로 "" 큰따옴표로 묶인 문자열을 이콜(=) 기호로 할당할 때 사용
const는 상수 라는 뜻
상수는 프로그램 안에 직접적으로 박혀 있는 값을 의미
프로그램이 끝날 때 까지 값 수정 불가능
(그래서 free( ... )를 사용하게 된다)
#include "prc.hpp" int main(){ char input[100]; const char* myString = "HelloWorld"; // HelloWorld 라는 문자열은 프로그램상 직접적으로 박혀있다, 값 수정 불가능 strcpy 사용 안됨 printf("%s", myString); return 0; } |
메모리 동적할당
: 배열이나 데이터를 컴퓨터의 메모리중 힙(Heap) 영역에 자리시키는 것
Heap 영역은 함수의 실행주기와 무관하게
프로그램 종료시까지 살아남은 메모리 공간이다
malloc ( ... )
: 메모리를 동적할당할 수 있는 함수
cstdlib 헤더파일에 선언되어 있음
Type v = (Type*)malloc(sizeof(Type));
와 같은 방법으로 Type의 크기만큼 1개의 공간을 Heap 영역에 할당한다
메모리 동적 할당은 cstdlib 헤더파일에 존재하는 malloc( ... ) 함수를 이용해서 할당되게 됨
이 동적 할당하는 함수인 malloc 함수를 이용하게 되면 컴퓨터의 메모리 Heap 이라고 하는 영역에 메모리가 할당이 되며,
이 Heap 영역의 메모리의 주소값을 malloc 이라는 함수가 반환해 줌
주소값이 반환되었으니까 포인터 데이터 타입이 반환이 되고
이 메모리를 얼마나 할당하느냐 (데이터 타입의 크기만큼만 할당하느냐)
혹은 데이터 타입의 크기보다 훨씬 크게 만드느냐에 따라서
단일 메모리 할당이 가능하거나, 배열 또한 메모리 동적 할당을 할 수 있게 됨
#include "prc.hpp" struct Marine{ int hp; int mp; char name[20]; }; Marine* foo(){ // Marine이라는 구조체 포인터를 return 하는 함수인 foo 만들기 Marine* m = (Marine*)malloc(sizeof(Marine)); (*m).hp = 100; (*m).mp = 50; strcpy((*m).name, "Jim Maynor"); return m; // Marine의 m 구조체변수의 주소값을 return 해줌 // foo라는 함수는 Marine 이라는 구조체 변수를 하나 만들고, 구조체 변수에 체력을 100이 들어가고 마력이 50이 들어감 } int main(){ Marine* m = foo(); // 주소값 m을 받아와서 Marine의 값의 구조체 포인터 변수에다가 주소값 집어넣어주기 printf("%s", (*m).name); free(m); return 0; } // 함수가 실행되고 나면 그 함수의 변수는 모두 다 파괴가 되지만 메모리 동적할당을 하게 되면 동적할당된 메모리는 파괴되지 않고 heap 영역에 남아 있다. 여기서 파괴되는 것은 주소값이 파괴가 되는 것이지 실제로 동적할당된 메모리 그 자체에 실제 값은 파괴가 되지 않기 때문 // 함수의 life cycle, 함수가 시작되고 종료되고 함수가 살아 있고 죽음의 관계 없이 무결한 변수 데이터를 만들고 싶을 때 주로 사용 // 그리고 (Marine*)malloc(sizeof(Marine)); 이런식으로 동적할당한 것은 char name[20]; 이렇게 정적으로 할당했던 것과는 다르게 가변적 크기의 배열 변수를 만들 수 있게 해줌 |
-> 표현
: 동적 할당된 구조체의 포인터 변수의
'멤버 변수'에 접근하기 위하여 사용할 수 있는 표현
동적 할당된 구조체의 멤버에 접근 가능
(*변수).멤버 를 변수 ->멤버 와 같은 방법으로 멤버에 접근
Hero*h = (Hero*)malloc(sizeof(Hero));
h->agility = 48;
위 예제 코드의 (*m). 을 m-> 로 바꾸면 됨
free ( ... )
: cstdlib 에 포함된 함수
동적할당된 변수, 배열 등등은
함수의 라이프사이클에 관계없이 계속 살아있는데
이것은 자동으로 메모리가 반환되지 않는다는 것
즉, malloc 으로 할당된 메모리 공간은 프로그래머가 free 함수를 사용하기 전까지
지속적으로 메모리 영역을 차지하고 있다
이것은 free() 라는 함수를 이용해 해제하지 않으면 메모리 누수의 원인이 된다
동적 메모리 할당 - 배열
Type*v = (Type*)malloc(sizeof(Type) * size);
: 이는 근본적으로 배열이 포인터와 같은 원리이기 때문에
malloc으로 할당될 메모리의 양만 더 크게 잡아주면 동적으로 '배열' 을 선언할 수 있다.
즉, 동적 메모리 할당 함수인 malloc 함수로 가변 길이의 배열을 만들 수 있다.
size 에는 자신이 원하는 배열의 크기가 지정되면 된다
#include "prc.hpp" int main(){ // 동적배열할당을 활용을 해서 사용자로부터 입력을 받아 입력을 받은 숫자만큼의 배열을 할당하고 할당된 배열의 임의의 값을 집어넣은 다음에 출력 해 보기 int* myArray; int input; fseek(stdin, 0, SEEK_END); printf("숫자를 입력하시면 배열이 만들어집니다 : "); scanf("%d", &input); myArray = (int*)malloc(sizeof(int) * input); // malloc 이란 함수는 동적으로 뭔가 메모리를 잡아주는 것 (배열일수도 배열이 아닐수도), return은 항상 포인터 타입이 나오기 때문에 이걸 (int*) 으로 캐스팅을 해 주는 것, 캐스팅을 해주고 이것을 myArray주소값을 myArray에 집어넣어 주는 것, 실제 메모리는 heap 영역에 생기게 되고 그 메모리의 주소값을 return 해서 myArray에 집어넣어주게 되는 것, 그러면 젤 윗 코드 int* myArray에 주소값이 들어가고 우리는 그 주소값을 이용해 배열처럼 활용하게 되는 것, sizeof 는 몇바이트냐 이고 그 뒤 (int)는 4byte다 라는 것을 의미, sizeof(4byte)로 4byte 크기의 배열이 input의 개수만큼 메모리가 할당이 됨, 우리가 100이라는 숫자를 입력했을때 100*4byte 만큼 메모리가 할당이 됨 그것을 우리가 대괄호[]를 활용해서 사용할 수 있게 됨 이것이 메모리 동적할당 for (int i = 0; i < input; i++){ myArray[i] = i*10; } for (int i = 0; i < input; i++){ printf("myArray[%d] = %d\n", i, myArray[i]); } return 0; } |
과제형 연습 프로그래밍
사용자로부터 숫자를 입력받아
배열의 동적할당을 활용해 입력받은 숫자 만큼의 크기를 갖는 배열을 만들고
해당 배열에 2, 4, 6, 8, ... 로 증가하는 수열을 저장한 뒤 배열을 출력하세요
#include "prc.hpp" int main(){ int input; fseek(stdin, 0, SEEK_END); printf("숫자를 입력해주세요 : "); scanf("%d", &input); int* myArray; myArray = (int*)malloc(sizeof(int) * input); // malloc이라는 것은 void 포인터로 리턴을 하게됨, malloc이라는 함수를 실행을 하면 꼭 (int*)로 캐스팅 해줘야함 // int 크기만큼 이렇게 sizeof(int) 하게 되면 4byte가 나옴 4 *(곱하기) 입력한 사이즈(input) 만큼 48byte를 myArray에 만들어서 최초 주소값을 myArray에 할당해주게 되는 것 for (int i = 0; i < input; i++){ myArray[i] = i * 2 + 2; } for (int i = 0; i < input; i++){ printf("%d\n", myArray[i]); } free(myArray); return 0; } |
'C언어' 카테고리의 다른 글
심화 C 언어 7 (매크로 - C/C++의 독특한 매력) (0) | 2021.08.06 |
---|---|
심화 C 언어 7 (포인터 - 포인터의 포인터, 함수의 파라미터의 포인터) (0) | 2021.08.04 |
심화 C 언어 5 (포인터 2 - 포인터를 쓰는 이유) (0) | 2021.08.01 |
심화 C 언어 4 (포인터 1 - 기초) (0) | 2021.07.31 |
심화 C 언어 3 (문자열 - 문자의 '배열') (0) | 2021.07.30 |