반응형

📝배열

// 배열
#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int a=10, b=20, c=30, d=40;   // 비연속적으로 메모리에 저장
    int arr[4] = {10, 20, 30, 40}; // 연속적으로 메모리에 저장

    printf("%d %d %d %d\n", a, b, c, d); // 10, 20, 30, 40
    printf("%d %d %d %d\n", arr[0], arr[1], arr[2], arr[3]); // 10, 20, 30, 40

}

 

 

📝포인터

// 포인터
#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int a=10, b=20, c=30, d=40;// 비연속적으로 메모리에 저장
    int arr[4] = { 10,20,30,40 };// 연속적으로 메모리에 저장

    int* p = &a;   // a의 주소값을 보관 (물론 주소값을 보관하기 때문에 p라는 변수로서 할당된다.)
    int* pa = arr; // arr[0]의 주소값을 보관

    printf("p : %d, pa : %d\n", p, pa);                          // 1823472356, 1823472488
    printf("&a : %d, arr : %d\n", &a, &arr[0]);                  // 1823472356, 1823472488
    printf("p의 값 = a의 값 = %d\n", *p);                        // 10
    printf("pa의 값 = arr[0]의 값 = %d\n", *pa);                 // 10
    printf("&p(p의 주소) : %d, &pa(pa의 주소) : %d\n", &p, &pa); // 1823472536, 1823472568

    // 배열 Pointer의 경우 배열처럼 사용가능
    printf("%d %d %d %d\n", pa[0], pa[1], pa[2], pa[3]); // 10, 20, 30, 40

}

 

포인터메모리에 할당된 주소를 가르키게 된다

 

  • 자료형* 변수명 = &할당된 변수명
    • 할당된 변수명의 주소(&)를 기억하는 변수가 만들어지게 된다.
    • *변수명을 통해 해당 주소의 실제 값을 읽어올 수 있다

배열의 경우 연속된 공간에 저장한다 그래서 포인터를 이용해 해당 주소를 가르키게 되면 포인터 변수명[0], 포인터 변수명[1] 과 같이 실제 값을 가져올 수 있습니다

 

📝메모리 저장 영역 (stack, Heap)

// 데이터 영역
#include <stdio.h>
#include <stdlib.h>

int g = 30; // G-D 영역 (전역변수, 정적변수, 상수)

int main() 
{
    int m = 20; // stack 영역 (함수내의 변수)
    int n = 20; // stack 영역

    int* p; // stack 영역
    p = (int*)malloc(4); // Heap 영역 (4byte 할당)

    *p = 10; // Heap 영역에 10 할당
    printf("%d", *p);

    // 4byte의 크기를 Heap 영역에 생성 후 p라는 포인터 변수가 그 주소값을 가르키게 된다.

    free(p); // 영역 할당을 free로 제거 시켜야 사라지게 된다.
}

메모리는 크게 2가지로 나뉘는데 stack영역과 Heap 영역으로 나뉘게 됩니다.

 

📝stack영역의 경우

호출된 함수가 마치고 복귀할 주소 및 데이터(지역변수, 매개변수, 리턴 값 등)를 임시로 저장하는 공간입니다 만약 재귀함수가 많이 발생해 stack영역을 초과하게 되면stack overflow 에러가 발생하게 됩니다. Stack은 컴파일 타임에 크기가 결정되기 때문에 무제한으로 할당 할 수 없습니다

 

📝Heap영역의 경우

런타임(프로그램 동작) 시 크기가 결정됩니다. malloc등으로 Heap영역의 메모리를 사용해 원하는 공간만큼 할당해 사용합니다. 이렇게 공간을 할당하고 해제하지 않으면 Memory Leak이 발생하게 됩니다. JAVA의경우 JVM이 이 행위를 대신 해주죠 Stack의 비해 메모리 공간이 많지만 포인터로 접근해야 하기 때문에 속도가 느립니다

 

 

📝 정적배열, 동적배열

// 정적배열, 동적배열
#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int arr[20]; // 정적배열

    arr[0] = 0;
    arr[1] = 10;
    arr[2] = 20;
    arr[3] = 30;
    arr[4] = 40;

    for (int i = 0;i < 5; i++) {
        printf("%d\n", arr[i]); // 0, 10, 20, 30 , 40
    }

    int* p;
    p = (int*)malloc(40); // 동적 배열

    p[0] = 0;
    p[1] = 10;
    p[2] = 20;
    p[3] = 30;
    p[4] = 40;

    for (int i = 0;i < 5; i++) {
        printf("%d\n", p[i]); // 0, 10, 20, 30 , 40
    }

    free(p);
    
    // sizeof를 이용한 할당방식
    int* ps;
    ps = (int*)malloc(sizeof(int) * 5); // sizeof(int) * 5 → int형 5개를 생성

    ps[0] = 0;
    ps[1] = 10;
    ps[2] = 20;
    ps[3] = 30;
    ps[4] = 40;

    for (int i = 0;i < 5; i++) {
        printf("%d\n", ps[i]); // 0, 10, 20, 30 , 40
    }

    free(ps);

}

정적배열의 경우 stack영역을 사용하는 걸 의미하고 동적배열의 경우 Heap영역을 사용하는 걸 의미합니다.

 

📝 사용자에게 값을 입력 받기

// 사용자에게 배열크기 입력받기
#include <stdio.h>
#include <stdlib.h>

int main() 
{
    int size = 0;
    printf("배열의 크기를 입력해주세요 : ");
    scanf_s("%d", &size); // size을 사용자에게 입력 받는다.

    // int arr[size]; // 정적배열인 경우 배열크기에 변수 할당 불가
    int* pa = (int*)malloc(sizeof(int) * size); // 동적배열은 가능하다.


    for (int i = 0; i < size; i++) {
    printf("[%d] 배열의 값을 입력해주세요 ", i);
    scanf_s("%d", &pa[i]); // 배열을 입력해주세요
    }

    for (int i = 0; i < size; i++) {
        printf("pa[%d] : %d\n", i, pa[i]);
    }
}

 

반응형