객체지향 - C++

C언어 복습

Reddish 2023. 4. 18. 19:55

1. stdio.h (표준 입출력)

- scanf, printf

2. 배열

int main()
{
		int arr[5][5];
		int i, j;
		for(i = 0; i < 5; i++){
				for(j = 0; j < 5; j++){
						if(i >= j) arr[i][j] = i + 1;
						else arr[i][j] = 0;
				}
		}
		for(i = 0; i < 5; i++){
				for(j = 0; j < 5; j++){
						printf("%d ", arr[i][j]);
				}
				printf("\n");
		}
		return 0;
}

/*
1 0 0 0 0
2 2 0 0 0
3 3 3 0 0 
4 4 4 4 0
5 5 5 5 5
*/

 

3. 포인터

- 어떤 변수를 저장한 메모리 주소

프로그램에서의 메모리 구조

다음과 같이, 데이터 영역, 스택 영역, 힙 영역, 코드 영역으로 나뉜다. 

데이터 영역에는 전역 변수, 정적 변수가 들어가게 된다.

스택 영역에는 지역변수들이 들어가고, 힙에는 동적 변수가 들어간다.

함수는 코드에 저장된다.

 

 

- 메모리 주소

  • 주소 : 바이트 단위의 번호
  • 주소를 8비트로 표현 -> 2^8 (0~255번지)의 주소값
  • Windows -> 32bit또는 64bit

다음과 같이 메모리에 들어간다.

  • 변수의 주소 : &연산자(참조)
  • int num = 5;
  • num의 주소 : &num
  • 포인터 변수를 통한 변수 접근 : *연산자 사용
    • int *pnum = &num;
    • *pnum = 5;   -> pnum 에는 5가 들어간다.
  • 포인터 연산
    • 증가, 감소, 덧셈 뺄셈의 겨우, int 형 포인터의 경우 1증가 -> int형 변수의 크기인 4만큼 증가
#include <stdio.h>

int main()
{
    int var = 5;
    int *p = &var; // 포인터 변수 선언 및 var 주소값 입력

    printf("var의 주소 : %d\n", &var); // var 주소
    printf("var의 값 : %d\n", var); // var의 값
    printf("p의 주소 : %d\n", &p); // p의 주소
    printf("p의 값 : %d\n", p); // var의 주소
    printf("p가 가리키는 변수의 값 : %d\n", *p);  // 5출력

    p++; // 4증가

    printf(">> 변경후 \n");
    printf("p의 값 : %d\n", p);

    return 0;
}

 

4. 배열과 포인터

- 배열은 포인터 처럼, 포인터는 배열처럼 사용 가능하다.

- 배열에 대한 포인터 연산의 적용 

int num[5] = {0, 1, 2, 3, 4};

int *pnum = num;

pnum++; // 다음 원소를 가리킴.
pnum[0], pnum[1] ...과 같이 사용 가능
pnum[2] == *(pnum + 2)

배열 명에 대한 주소는 변경이 불가하다.

5. 메모리 동적 할당

동적 할당 : 프로그램이 돌아가는 중에 메모리를 할당하는 것.

- 메모리 동적 할당 및 해제 함수 -> malloc(), free()

#include <stdio.h>
#include <stdlib.h> // srand, rand 함수
#include <time.h> // time 함수

int main()
{
    int i, arr[10], *p;

    srand((unsigned)time(NULL)); // seed값 결정함수

    for (int i = 0; i < 10; i++)
    {
        arr[i] = rand(); // 랜덤값 대입
    }

    p = (int *)malloc(sizeof(int) * 10); //int형 10개 메모리 도엊ㄱ할당

    for (i = 0; i < 10; i++)
    {
        p[i] = arr[i]; // 포인터는 배열처럼 사용 가능
    }
    printf("index\tarr\tp\n");
    for (int i = 0; i < 10; i++)
    {
        printf("%d\t%d\t%d\n", i, arr[i], p[i]);
    }
    free(p); // 메모리 해제

    return 0;
}

6. 함수

매개변수 전달 방식

  • 값에 의한 전달(Call by Value)
#include <stdio.h>
#include <stdlib.h> // srand, rand 함수
#include <time.h> // time 함수

int main()
{
    int i, arr[10], *p;

    srand((unsigned)time(NULL)); // seed값 결정함수

    for (int i = 0; i < 10; i++)
    {
        arr[i] = rand(); // 랜덤값 대입
    }

    p = (int *)malloc(sizeof(int) * 10); //int형 10개 메모리 도엊ㄱ할당

    for (i = 0; i < 10; i++)
    {
        p[i] = arr[i]; // 포인터는 배열처럼 사용 가능
    }
    printf("index\tarr\tp\n");
    for (int i = 0; i < 10; i++)
    {
        printf("%d\t%d\t%d\n", i, arr[i], p[i]);
    }
    free(p); // 메모리 해제

    return 0;
}
  • 참조에 의한 전달 (Call by Reference)
#include <stdio.h>

void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main()
{
    int a = 2;
    int b = 3;

	printf("a : %d, b : %d\n", a, b);
	swap(a, b);

	printf("a : %d, b : %d\n", a, b);
	return 0;
}
  • 배열의 전달
#include <stdio.h>

void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main()
{
    int a = 2;
    int b = 3;

	printf("a : %d, b : %d\n", a, b);
	swap(a, b);

	printf("a : %d, b : %d\n", a, b);
	return 0;
}

 

7. const 와 포인터

  1. const 상수 선언
    • const double PI = 3.14;
    • 변경 못함
  2. 함수 매개변수의 상수화
    • int sum(const int x, const int y) { return (x + y); }
    • 함수 내에서 x, y의 값 변경 불가
    • 실매개변수로 일반 변수와 const 상수 모두 사용 가능 (형식 매개변수가 const가 아닌 경우에는 실매개변수로 const상수 불가)
  3. const와 포인터
    • int *pnum = &num;
  4. 포인터의 상수화
    • num의 상수화 → const int *pnum = &num; →num을 고정
    • pnum의 상수화 → int *const pnum = *num; → pnum을 고정

 

8. 구조체

- 동질 또는 이질적인 데이터 여러개를 하나의 그룹으로 처리

- 사용자 정의형 자료구조

- 단방향 링크드 리스트 만들기

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

struct Node
{
    int data;
    struct Node *next;
};


int main()
{
    int i;
    struct Node *pStart = NULL; // 첫번째 노드 포인터
    struct Node *pEnd = NULL; // 마지막 노드 포인터
    struct Node *Current;

    for (int i = 1; i <= 5; i++)
    {
        // 노드 생성
        Current = (struct Node *) malloc(sizeof(struct Node));
        Current->data = i;
        Current->next = NULL;

        if(pStart == NULL)
        {
            pStart = pEnd = Current;
        }
        else
        {
            pEnd->next = Current;
            pEnd = Current;
        }
    }

    Current = pStart;
    while(Current != NULL)
    {
        printf("%d\n", Current-> data);
        Current = Current->next;
    }
}