컴퓨터 언어/C

[C] C언어 6일차 포인터

훈츠 2020. 3. 15. 14:04
반응형

안녕하세요. 훈츠 입니다. 이번 시간에는 포인터에 대해 정리 해보려고 합니다. 어렵게 느껴졌는데 차근차근 정리 해보니 정리가 되네요. 같이 한번 보시죠.

포인터 

메모리와 변수

  • 메모리 에서 데이터를 읽어오는 방법
  • 메모리 주소 -> 데이터 위치 
  • 메모리의 주소와 데이터 타입을 알면, 데이터를 읽거나 저장 할 수있다.
  • 포인터의 역활 : 임의의 메모리에 접근하여 값을 저장하거나 읽는 역활 
  • 포인터 변수 : 메모리 주소를 저장 하는 변수
  • 일반 변수와 포인터 변수의 공통점과 차이점 
  공통점 차이점
일반 변수 값 저장 상수 저장
포인터 변수 값 저장 메모리 주소 저장 

'*' 참조 연산자 아스트리크 

  • 선언된 변수가 포인터 변수임을 나태내는 역활 
    • ex) int *pVar; == int* pVar;
  • 포인터 변수에 저장된 메모리 주소로 접근한 메모리 영역의 데이터(값)을 의미

포인터 선언 과 데이터 형 

  • 선언 형식 
    • 데이터형 *변수명 = int *pPtr;
  • 데이터형에 따른 의미 
구분 의미
char * 문자형 메모리 주소를 저장
int * 정수형 메모리 주소를 저장
float * 실수형 메모리 주소를 저장 
  • 포인터 변수의 선언과 의미

scanf_s 함수의 사용 

  • & 는 메모리 주소 접근 이므로, 포인터는 메모리 주소를 가지고 있으므로 & 연산자를 쓰지 않는다. 

 void 형 포인터

  • 의미 : 데이터형이 정해지지 않은 포인터 변수
  • 역활 : 모든 메모리 주소를 저장만 함. 
    • 접근을 위한 데이터형 변환 필요 
    • *(데이터형 *) 포인터명 
  • 형식 : void *ptr;

포인터 와 배열

  • 포인터로 배열을 다룰수 있습니다. 
    • 이유 : 같은 데이터형, 연속적인 메모리 할당 
  • 방법 2가지 
    • 1. 직접 접근 : pPtr + n
    • 2. 배열 형식으로 접근 : pPtr[n]..
  • 직접 접근법
    • 포인터 변수 + n 와 *( 포인터변수 + n ) 의 의미
      • pPtr + 1, pPtr + 2, pPtr +3...: 주소 접근시 
      • *(pPtr + 1), *(pPtr + 2), *(pPtr + 3)... : 값 접근시

  • 배열 형식 접근 
    • 포인터 변수[n] 의 의미
      • pPtr[0] , pPtr[1], pPtr[2]... : 주소 접근시
      • *pPtr[0], *pPtr[1], *pPtr[2]... : 값 접근시

널 포인터 

  • 아무것도 참조하지 않는 포인터 변수 
  • 저장하는 값 : 0, '\0', NULL
  • 포인터를 사용하여 할당한 메모리를 해제했을 때 

포인터를 활용한 메모리 생성과 해제 (malloc & free)

*void  malloc ( size_t size );

  • #include <stdlib.h> or <malloc.h> 포함
  • size_t : unsigned int 의 축약형 입니다. 
  • 할당한 메모리 공간이 부족하면 NULL, 0, '\0' 리턴
  • 할당한 메모리의 첫번 째 주소를 리턴 
  • 리턴형이 void * 이므로 형 변환을 통해 메모리 주소를 받아야 합니다. 

 void  free ( void *memblock );

  • memblock : 해제할 메모리 주소
  • 할당한 메모리는 반드시 해제 해줘야 합니다. 

malloc 과 free 활용예시

메모리 계산 키워드 sizeof 

  • 메모리 계산 키워드 sizeof
    • 데이터 형, 변수, 배열의 메모리 크기를 바이트 단위로 알려주는 키워드 
  • 형식
    • sizeof ( 변수 또는 데이터형 ), sizeof 변수 
    • sizeof ( int ), sizeof ( 변수명 ), sizeof ( 배열명 )
int arr[] = { 1,2,3,4,5 };
int nCnt = sizeof(arr) / sizeof(arr[0]); 
/*
sizeof(arr)는 전체 arr 바이트 크기
sizeof(arr[0]) 는 arr[0] int type의 크기 
두수를 나누면 추후, arr 갯수가 달라져도 같은결과를 얻을수 있으므로 nCnt에 상수값을 바로 대입하는
방법보다 효율적입니다. 
*/

포인터를 이용하여 배열을 함수로 전달

  • 포인터 자체는 주소값만 가지고 있으므로 배열의 갯수는 별개로 전달해줘야합니다. 

함수 출력후, arr값 출력된걸 확인해보면 11,12...15 가 된걸 확인 할수있습니다. 

int main() {
		
	int* pPtr;
	pPtr = (int*)malloc(sizeof(int) * 5);
	for (int i = 0; i < 5; i++) {
		pPtr[i] = 3;
		printf("malloc value %p, %d\n", &pPtr[i], pPtr[i]);
	}
	printf("before free %p\n", pPtr);
	free(pPtr);
	printf("after free %p\n", pPtr);
	
	_getch(); //waiting for step 
	return 0;
}

문자열 다루기 

  • 배열 에서 문자열 다루기 
    • read / write 수정이 가능함
  • 포인터에서 문자열 다루기 
    • read 전용 
int main() {
		
	char str[10] = "abcedfg";
	printf("%s \n", str); //출력 abcdedfg
	str[0] = 'z'; //변경 가능 
	printf("%s \n", str); //출력 zbcdedfg

	
	char* pStr = "abcedfg";
	printf("%s \n", pStr);//출력 abcdedfg
	pStr[0] = "z";        //오류 발생 
	printf("%s \n", pStr);


	_getch(); //waiting for step 
	return 0;
}

출력 화면 

정리 

  • & 변수는 변수의 메모리 주소를 의미하듯, *포인터는 메모리 주소로 접근(참조)한 값을 의미합니다. 
  • 변경되지 않는 문자열을 다룰때 편리합니다. 
  • 다음 예시를 잘 보면 접근을 어떻게 해야하는지 이해가 됩니다. 
char str[] = "C Point example";
char* ptr = &str[0]; //배열에 첫번째 주소를 넘겨 줍니다. 

cout << ptr << endl; // ptr 이렇게 하면 다 읽어온다. 
//출력 : C Point example

cout << *ptr << endl; // ptr 접근한 값 하나, *ptr ++ 주소값 증가시, 다음값 읽어옴. 
//출력 : C

cout << ptr[index] << endl; // ptr[index] 접근한 값 하나, index++ 증가시, 다음값 읽어옴. 
//출력 : C 
반응형

'컴퓨터 언어 > C' 카테고리의 다른 글

[C] C언어 7일차 구조체와 TypeDef  (0) 2020.03.16
[C] C언어 7일차 포인터2  (0) 2020.03.16
[C] C언어 5일차 배열  (0) 2020.03.14
[C] C언어 4일차 함수  (0) 2020.03.13
[C] C언어 3일차 반복문과 분기문  (0) 2020.03.12