C Lang - 포인터

한준수·2023년 6월 14일
0

C-Lang

목록 보기
3/12

📖 포인터 학습 전 배열 응용

C언어에서 다른 랭귀지에서 사용되는 스택을 만드려면 어떻게 해야할까?

📌 스택(Stack)

스택은 프링글스 생각하면 쉽다.
한쪽으로만 입출력이 가능하니 당연히 가장 마지막에 들어간 것이 가장 먼저나오고 가장 먼저 들어간 것이 가장 나중에 나오게되는 LIFO / FILO 구조를 가지고 있다.

⌨ C 배열로 스택 만들기

#include <stdio.h>

void main(){
	char stack[5];
    int top=0;
    
    stack[top] = 'A';
    printf(" %c 자동차가 터널에 들어감\n", stack[top]);
    top++;
    
    stack[top] = 'B';
    printf(" %c 자동차가 터널에 들어감\n", stack[top]);
    top++;
    
    stack[top] = 'C';
    printf(" %c 자동차가 터널에 들어감\n", stack[top]);
    top++;
    
    printf("\n");
    
    top--;
    printf("%c 자동차가 터널을 빠져나감\n", stack[top]);
    stacktop = ' ';
    
    top--;
    printf("%c 자동차가 터널을 빠져나감\n", stack[top]);
    stacktop = ' ';
    
    top--;
    printf("%c 자동차가 터널을 빠져나감\n", stack[top]);
    stacktop = ' ';
}

💻 출력


📖 메모리와 주소

  • 메모리는 바이트(Byte) 단위로 나뉘며, 각 바이트에는 주소가 지정됨
  • 정수형 변수의 크기는 4바이트이므로 이 메모리에 정수형 변수 a를 선언하면 임의의 위치에 4바이트가 자리잡음.
  • 변수가 위치하는 곳 : 주소(address)
  • 변수의 주소를 알려면 변수 앞에 '&'를 붙임
  • a의 주소(&a) = 1036번지 , b의 주소(&b) = 1048번지

⌨ 직접 주소를 확인해보자

#include<stdio.h>

void main(){
	int a = 100;
    int b = 20;;
    
    printf("변수 a의 주소는 %d 입니다. \n", &a);
    printf("변수 b의 주소는 %d 입니다. \n", &b);
}

💻 출력

📌 정수형 배열의 메모리 할당

  • 배열의 주소 표현
    • aa[0]의 주소(&aa[0]) = 1031
    • aa[1]의 주소(&aa[1]) = 1035
    • aa[2]의 주소(&aa[2]) = 1039
  • aa 배열 자체 주소 = 전체 배열의 주소 = 1031 번지
    • 배열 aa의 주소를 구할 때는 '&'를 쓰지 않고, 단순히 'aa'로 표현한다.

💻 배열 주소 구하기

#include <stdio.h>
void main(){
	int aa[3] = {10, 20, 30};
    
    printf("aa[0]의 값은 %d, 주소는 %d \n", aa[0], &aa[0]);
    printf("aa[1]의 값은 %d, 주소는 %d \n", aa[1], &aa[1]);
    printf("aa[2]의 값은 %d, 주소는 %d \n", aa[2], &aa[2]);
    
    printf("배열이름 aa의 값(=주소)는 %d\n", aa);
}

💻 출력

✍ 배열 + int

위에서 배열 aa를 만들었는데 'aa + 1'이 무슨 의미인지 알아보자.

aa는 정수형 변수가 아닌 배열이다.
배열에 + 1을 하라는 것은 1을 더하라는 것이 아닌 배열 aa의 위치에서 한 칸 건너뛰라는 의미이다.
한 칸은 현재 aa가 정수형 배열이므로 4바이트를 의미한다.

⌨ 직접 해보자.

#include<stdio.h>

void main(){
	int aa[3] = {10, 20, 30};
    
    printf("&aa[0]는 %d, aa+0은 %d \n",&aa[0], aa+0);
    printf("&aa[1]는 %d, aa+1은 %d \n",&aa[1], aa+1);
    printf("&aa[2]는 %d, aa+2는 %d \n",&aa[2], aa+2);
}

💻 결과


📖 포인터

주소가 뭔지 대충 알았으니 포인터에 대해 알아보자

위와 같이 변수를 선언하면 아래와 같이 메모리에 변수가 자리를 잡는다.

  • 1의 문자형 변수 ch는 1바이트를 차지하므로 주소 1031번지에 1바이트가 자리잡음(&ch는 1031을 뜻하는 주소값)

  • 2의 포인터 변수(char*) p는 1032~1035번지에 4바이트가 자리 잡음

    ✍ 포인터 변수는 크기가 4바이트이다.

  • 3의 변수 ch에 'A 값'을 넣고 4의 포인터 변수 p에 변수 ch의 주소값인 &ch를 넣음

  • &ch는 1031번지를 의미하므로 포인터 변수 p에는 1031이 들어간다.

⌨ 코드

#include <stdio.h>

void main(){
	char ch;
    char* p;
    
    ch = 'A';
    p = &ch;
    
    printf("ch가 가지고 있는 값: ch ==> %c \n", ch);
    printf("ch의 주소(address): &ch ==> %d \n", &ch);
    printf("p가 가지고 있는 값 : p ==> %d \n", p);
    printf("p가 가리키는 곳의 실제값 : *p ==> %c \n",*p);
}

💻 결과


결과를 보면 변수 p가 두개의 결과를 냈다.
p 에 ch의 메모리 주소를 대입했으니
p를 출력하면 ch의 주소 값이 나오고
*p를 출력하니 메모리 주소에 있는 값을 가져온 것이다.

📌 포인터로 값 교환

포인터를 사용하는 이유는 동적 메모리 할당이나 메모리관리, 속도 등 많은 것이 있지만 메모리 직접 접근이 가능하다는 이유도 있다. 아래 코드를 보자

#include <stdio.h>

void main(){
	char ch;
    char *p;
    char* q;
    
    ch = 'A';
    p = &ch;
   
    q = p;
    
    *q = 'Z'
    
    printf("ch가 가지고 있는 값: ch ==> %c \n\n", ch);
}

💻 결과

* 기호는 데이터형에 붙이는 변수명에 붙이든 상관 없다.


📖 배열과 포인터의 관계

배열을 s[8]이라고 선언하면 s는 변수가 아닌 주소값이 된다.

#include<stdio.h>

void main(){
	char s[8] = "Basic-C";
    char *p;
    
    p = s;
    
    printf("&s[3] ==> %s\n", %s[3]);
    printf("p+3	==> %s\n\n", p+3);
    
    printf("s[3]  ==> %c\n", s[3]);
    printf("*(p+3) ==> %c\n",*(p+3));
}

💻 결과


%s[3]과 p+3은 주소값을 나타내기 때문에
해당 주소부터 마지막 글자까지를 출력하는 것이고
,
s[3]과 *(p+3)은 실제 값을 의미하므로 i를 출력하는 것이다.

⌨ 문자열 배열과 포인터의 응용

#include<stdio.h>

void main(){
	char s[8] = "Basic-C";
    char *p;
    int i;
    
    p = s;
    
    for(i = sizeof(s)-2; i >= 0; i--){
    	printf("%c", *(p+i));
    }
    
    printf("\n");
}

💻 결과

C-cisaB 가 출력된다.


⌨ 퀴즈

  • 입력한 두 값을 포인터를 활용하여 교환하는 프로그램을 작성하시오.
  • 실행결과
답보기
#include<stdio.h>

void main(){
	int a;
    int b;
    int *p1;
    int *p2;
    int tmp;
    
    printf("a값 입력 : ");
    scanf("%d", &a);
    printf("b값 입력 : ");
    scanf("%d", &b);
    
    p1 = &a;
    p2 = &b;
    
    tmp = *p1;
    *p1 = *p2;
    *p2 = tmp;
}

0개의 댓글