본문 바로가기

프로그래밍/C 프로그래밍

[C언어] 포인터 및 참조

 

 

포인터 변수?
변수의 주소값을 갖는 특별한 변수

  • 변수: 특정 데이터 값을 갖고 있음
  • 포인터: 특정 데이터가 저장된 기억장소의 주소(번지)값을 가지고 있음
    • 따라서 포인터는 기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용한다.

포인터의 사용

  • 포인터가 유효한 대상을 가리키게 한 후 사용해야 한다.
ptrVar = &var; // ptrVar이 var를 가리키게 함
*prtVar = value; // prtVar을 이용하여 var을 액세스
//& 주소 계산 연산자
//*prtVar: 포인터 prtVar가 가리키는 곳

 

# 포인터 변수의 선언

  • int *p
    • p: 포인터 변수로서 정수형 자료가 수록되어 있는 주소를 갖고 있다.
    • *p: 해당 주소에 수록되어 있는 정수형 자료를 갖고 있다.
  일반변수 포인터변수
선언 int a; int *a;
값 할당 int a = 100; *a = 100;
주소 참조 &a a
주소 연산 불가능 a--; a++;

 

참조(reference)란?

  • 어떠한 대상을 가리키는 값(포인터와 유사)
  • 참조 변수는 참조 대상의 별명처럼 사용
  • l-value 참조: 실체가 있는 대상에 대한 참조
//올바른 참조 방법
int *p, i=4;
	p=&i;
    *p = 10;
//변수의 번지 출력 확인
#include <stdio.h>

int main(){
    int i = 127;
    int j;

    printf("%d, %x \n ", i , i); //%x: 16진수
    printf("%x \n", &i); // & 연산자 :주소 연산자.

    printf("%#x \n", &i); //#x: 16진수 출력시 0x를 먼저 표시

    printf("%x \n", &j);
    printf("%#x \n", &j); 

} 

/*
결과
127, 7f
 62fe1c
0x62fe1c
62fe18
0x62fe18

*/

 

# char형 포인터

  • 포인터는 문자열 처리에 효과적이다.
  • 값을 참조할 때와 달리 포인터 변수에 주소를 치환하지 않는다. (문자열의 시작주소 가진다.)

[실습] 입력된 문자열 역방향으로 출력

#include <stdio.h>
#include <conio.h> //콘솔 입출력함수. 
#include <string.h>

int main(){
	char buffer[80], *p=buffer;
	int len, i=0;
	
	printf("Input String: ");
	scanf("%s", p);   //사용자가 입력한 문자열을 buffer에 저장. 
	
	len=strlen(p); 
	while(*p)  //문자열 끝까지 포인터 'p'를 이동시킨다. 이때 p는 마지막 문자 지나서 null(\0)을 가리킨다. 
		p++;
	
	printf("Inverse String: ");
	while(i<len){   //문자열 길이만큼 반복. 
		p--;       //포인터 한 칸 뒤로 이동. 
		putchar(*p); //포인터가 가리키는 문자 출력.( 감소된 포인터 위치에 따라 역방향 출력)  
		i++;
	
	}	
	putchar('\n');
	getch(); //종료전 대기, 사용자가 키를 누를때까지 대기. (콘솔 창 바로 닫히는거 방지하기 위해 사용.) 
	
}

 

# 포인터와 배열

  • 배열은 포인터의 일부분, 서로 호환적.
  • 모든 배열은 포인터로 표현 가능
A+i == &A[i]
A[i] == *(A+i)
*(p+i) == p[i]
  • 배열에서는 값 변경 불가
    • 배열 A[i]에서 A++, A-- 와 같이 값 변경 불가
    • 포인터 *p에서는 p++, p--와 같이 값 변경 가능.
  • 기억공간 확보
    • 배열: 기억공간 중 자료영역 고정적 확보
    • 포인터: 기억공간 중 자료영역 유동적으로 확보
      • 필요할 때만 자료용 기억 공간 확보
      • 자료의 개수가 가변적일 경우 효과적
    • 포인터가 배열보다 활용의 폭이 넓다.

 

[실습] 주어진 정수에서 최댓값, 최솟값 찾는 프로그램

#include <stdio.h>

int main(){
	int A[] = {76,-59,-34,90,169,-12,13,103,3,29}; 
	int i, *p, max=-1000, min=1000;
	int maxloc, minloc;
	
	p=&A[0]; //포인터변수 p에 배열 A의 시작주소(첫 번째 요소) 대입
	printf("배열의 값[]={");
	for (i=0; i<10;i++){   // *(p+i)는 A[i]와 동일.
		if(*(p+i) > max){ // 현재의 요소가 최댓값보다 크면 max 업데이트, 위치 저장. 
			max = *(p+i);
			maxloc = i+1; 
		}
		if(*(p+i) < min){
			min =*(p+i);
			minloc = i+1;
		} 
		printf("%d \t", *(p+i)); //  현재 요소 값 출력. 
		
	} 
	
	printf("} \n");
	printf("최댓값 ==> %d, 위치 ==> %d 번째 \n", max, maxloc);
	printf("최솟값 ==> %d, 위치 ==> %d 번째 \n", min, minloc);
}

/*
배열의 값[]={76         -59     -34     90      169     -12     13      103     3       29      }
최댓값 ==> 169, 위치 ==> 5 번째
최솟값 ==> -59, 위치 ==> 2 번째
*/

 

[실습] 2개의 배열 a[], b[]의 내용 서로 교환하는 프로그램

#include <stdio.h>

swap(char *x, char *y){
	char temp;
	while(*x){
		temp = *x;
		*x = *y;
		*y = temp;
		x++;
		y++;
	}
	return temp;
}

int main(){
	static char a[]="SEOUL";
	static char b[]="KOREA";
	printf("<교환전> \n");
	
	printf("a[] = %s \n ", a);
	printf("b[] = %s \n ", b);
	
	swap(a,b);

	printf("<교환후> \n");
	
	printf("a[] = %s \n ", a);
	printf("b[] = %s \n ", b);	
	
	
	
}

 

[실습] 문자열에서 한글만 추출하는 프로그램

#include <stdio.h>

int main(){
 	unsigned char *p = "Computer Science 컴퓨터과학과";
	unsigned char buff[20] = {0, };   // 추출될 한글 문자 저장할 버퍼. 
	
	int i = 0;
	
	while(*p){ //문자열 끝에 도달할 때까지 반복. 
		if(*p>127){//한글 검색 조건(한글은 2byte로 구성되기 때문에 ASCII코드 값이 127 이상임. (첫바이트 128) 
			buff[i++] = *p; //한글문자 버퍼에 저장하고 인덱스 증가시킴. 
		}
		p++;
	} 
	puts(buff);
} 

/*
입력 문자열: "Computer Science 컴퓨터과학과"
출력: 컴퓨터과학과
*/

 

 [실습] 소문자로 된 문자열 대문자로 변환                                                                                                                         

#include <stdio.h>

int main(){
	char arr[]="programming";
	char *prt;
	int bigchar;
	prt=arr;
	printf("before: %s \n\n", arr);
	printf("after: ");
	
	while(*prt){
		bigchar = *prt -32; //대문자 변환
		printf("%c", bigchar);
		prt++;
	}
	printf("\n");
}

 

[실습] 문자열(대문자)를 입력받아 암호화

#include <stdio.h>
#include <conio.h>  // getche(), putch()
#include <ctype.h>  // isupper()

int main() {
    char code[] = "ZYXWVUTSRQPONMLKJIHGFEDCBA"; // 코드변환을 위한, 간단한 치환 암호 (A를 Z로, B를 Y로, ...)
    char ch[100];
    int i = 0;
    
    printf("Enter text: ");
    
    //getche() 문자를 읽어오고 바로 화면에 출력. 
    for (; (ch[i] = getche()) != '\r'; ) { // 읽어들인 문자가 엔터키(\r)가 아닌 한 반복
        if (isupper(ch[i])) {
            ch[i] = code[ch[i] - 65 ]; // 변환 수행
        }
        i++;
    }
    ch[i] = '\0'; // 문자열 끝을 표시
    printf("\n\n");

    printf("Transformed text: ");
    for (i = 0; ch[i] != '\0'; i++)
        putch(ch[i]); // 변환된 문자열을 출력

    return 0;
}

/*
Enter text: COMPUTER SCIENCE

Transformed text: XLNKFGVI HXRVMXV
*/

 

# 포인터 배열

  • 자료의 크기만큼 기억공간 할당

[실습] 노래제목 받아 역순 출력하기

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
	#define TOTAL 5
	char *song[10];
	char newSong[80];
	
	int i;
	for(i=0; i<TOTAL;i++){
		printf("애창곡: #%d?", (i+1));
		gets(newSong); //노래제목 입력 
		song[i] = (char *) malloc((strlen(newSong)+1) * sizeof(char)); //입력된 노래 제목의 길이에 맞게 메모리 동적 할당 
		strcpy(song[i], newSong);
	}
	printf("***입력한 노래 제목 ***\n");
	for(i=(TOTAL-1); i>=0; i--){
		printf("노래 #%d: %s\n", (i+1), song[i]);
		free(song[i]); // 동적으로 할당된 힙 공간 모두 돌려줘야 함. 
	}

 

# void 형 포인터

  • 프로그램 실행시에 자료형이 결정되는 경우에 사용
  • 저장하기 전에 명시적 형변환 필요
int a = 100;
char b = 'b';
void *p = NULL; // void 형 포인터 선언 후 초기화

p = (int *)&a; //void형 포인터 p에 int형 변수 a의 주소를 명시적 형변환 이용해서 대입.
printf("*p = %d\n, *(int*)p); 

p = (char*)&b;
printf("*p = %c\n, *(int*)p);

 

# 포인터와 기억공간의 대응관계

 

    int *p; p=100; 의 경우)

  • 포인터를 1 증가시키면 실제 주소는 int 형의 경우 4byte 증가
  • 포인터 p 주소 : 100
  • 포인터 p+1 주소: 104

# 포인터 연산

i = p-q,    ==> i = 4
i = q-p     ==> i = -4
단, 두 포인터간의 덧셈은 안된다.

 

# 이중 포인터

  • 형식: int **p;
  • 의미: 포인터 변수에 다시 포인터를 지정하는 것 👉 포인터에 대한 포인터
int **p;
p: 기억공간 주소
*p: 주소 p에 수록된 값.
**p: 주소가 *p인 곳에 수록되어 있는 값, 즉 int형 자

 

 

반응형

'프로그래밍 > C 프로그래밍' 카테고리의 다른 글

[C언어] 파일처리함수  (0) 2024.06.06
[C언어] 구조체와 공용체  (0) 2024.06.06
[C언어] 배열  (0) 2024.06.04
[C언어] 함수  (0) 2024.06.04
[C언어] 선택제어문/반복제어문  (0) 2024.06.04