포인터 변수?
변수의 주소값을 갖는 특별한 변수
- 변수: 특정 데이터 값을 갖고 있음
- 포인터: 특정 데이터가 저장된 기억장소의 주소(번지)값을 가지고 있음
- 따라서 포인터는 기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용한다.
포인터의 사용
- 포인터가 유효한 대상을 가리키게 한 후 사용해야 한다.
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 |