c

배열

haniru 2025. 11. 5. 22:06

1. 배열 선언 후 값 설정

ary[4] 를 출력한 결과가 -85.. 인것을 통해 쓰레기 값인걸 확인할 수 있다. 이는 프로그램이 예측할 수 없는 동작을 일으킬 수 있기 때문에 배열 초기화는 필수적이다. 또 코드는 배열 ary[5]의 유효한 첨자 범위인 ary[0]~ary[3]을 사용해서 정상적으로 값을 읽고 쓰는 과정을 보여준다. 유효 범위를 벗어난 첨자(ary[5] 이상)를 사용하면 런타임 오류나 예상치 못한 메모리 손상이 초래될 수 있다.

 

2. 배열 선언과 동시에 초기화

 

선언과 동시에 초기화 안된 배열

초기화 되지 않은 배열: 쓰레기 값이 들어가있다

 

선언과 동시에 초기화된 배열

초기화된 배열: 값이 잘 들어가있다. 선언과 동시에 중괄호 {} 를 사용하여 모든 요소에 원하는 값을 지정하면 배열 메모리 공간에 값이 채워진다.

 

선언과 동시에 부분 초기화

배열을 부분적으로 초기화하면 지정되지 않은 나머지 요소들은 모두 0으로 자동 초기화 된다

 

3. 배열의 코드 최적화, 리팩토링

초기 순차적 방식: 반복문 없이 배열의 각 요소를 하나씩 처리하는 방식이다.

반복문을 이용한 최적화 방식: 제공된 코드의 for 반복문을 사용하여 입력과 합계 계산을 동시에 처리함으로써 코드 줄임

 

4. 문자열 배열

문자열은 배열이기 때문에 일반 변수처럼 = 로 복사할 수 없다. 따라서 #include <string.h> 헤더 파일에 정의된 strcpy(대상 배열, 원본 배열) 함수를 사용해야 한다.

배열로 선언된 공간 자체(char str[80])는 스택에 있지만 초기값으로 사용된 문자열 리터럴("applejam")은 별도의 읽기전용 데이터 영역에 저장되었다가 복사된다
배열 str에 초기 문자열 applejam이 들어있지만 "grape"와 같은 짧은 문자열을 덮어쓰면 새로운 문자열의 널 문자가 끝나는 위치까지만 메모리가 갱신된다. 따라서 원래 문자열의 뒷부분인 a, m 등은 메모리에 그대로 남아있게 된다.

 

"tiger"가 str에 덮어쓰기 되면서 원래 내용 "cat"이 사라지고, str1의 내용이 str2로 복사되어 최종적으로 둘다 "tiger"가 된다

 

문자열 입출력: scanf, gets, printf, puts, fprintf, fputs

 

문자열 끝에 null 문자가 없을 때 쓰레기 값들이 문자처럼 해석되거나 프로그램의 다른 메모리 영역을 침범해서 예측 불가능한 결과를 초래한다. 따라서 문자열을 수동으로 조작할땐 반드시 문자열의 끝에 \0를 명시적으로 넣어줘야 한다

 

 

5. 동적 할당

일반적으로 선언하는 배열 (int ary[5]) 은 스택 메모리에 할당되며 배열의 크기가 컴파일 시점에 고정되기 때문에 배열의 크기가 프로그램 실행 중 사용자 입력(N)에 따라 달라져야 할 때 고정 크기의 배열은 사용할 수 없다

동적할당은 프로그램 실행중에 필요한 메모리 크기를 요청하고 할당받는 기술이다. 동적할당으로 얻은 메모리 공간은 힙 메모리 영역에 저장된다.

더보기

📦 힙 (Heap) 메모리란?

힙(Heap) 메모리개발자가 수동으로 관리하는 메모리 영역입니다.

  • 특징: 크기의 제약이 비교적 적고, 함수가 종료되어도 메모리가 자동으로 해제되지 않고 데이터가 유지됩니다.
  • 관리 책임: 개발자가 malloc으로 할당한 후, 사용을 마쳤을 때 반드시 free 함수로 수동 해제해야 합니다. 해제하지 않으면 메모리 누수(Memory Leak)가 발생합니다.

 

더보기

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> // malloc, free 사용

int main()
{
    
int N, X;
if (scanf("%d %d", &N, &X) != 2) {
    return -1; // 입력 에러 처리
}

// 동적 할당
// malloc - 힙 공간을 만들고 시작주소 값을 A 라는 변수에 주소가 들어가게 된다
int* A = (int*)malloc(N * sizeof(int));

if (A == NULL) { // 에러처리 구문
    printf("memory error");
    
    // 응용/임베디드 인지에 따라 성공일수도 실패일 수도 있다
    return -1; // 메모리 할당 실패 처리
}

// 수열 A 입력
for (int i = 0; i < N; i++) {
    scanf("%d", &A[i]);
}

// X보다 작은 수 출력
for (int i = 0; i < N; i++) {
    if (A[i] < X) {
        printf("%d ", A[i]);
    }
}

// 할당된 메모리 해제 (가장 중요!)
free(A);

return 0;

}

 

 

문제

짝수 성적 구하기

 

max값 구하기

 

팩토리얼

1. 재귀방식 - 함수가 자기 자신을 호출하여 문제를 해결하는 방식이다

이해가 잘 안됐는데, 일단 factorial(5), factorial(4), factorial(3), factorial(2), factorial(1) 순으로 재귀 호출을 한 다음

1 * factorial(2), 1 * 2 * factorial(3), 1 * 2 * 3 * factorial(4), 1 * 2 * 3 * 4 * factorial(5) 가 되어서 최종적인 결과가 5! 가 되는듯

더보기

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

int factorial(int num);

int main()
{
    int N = 5;
    int result = factorial(N);
    
    printf("%d! = %d", N, result);
    
    return 0;

}

int factorial(int num) {
    if (num > 0) {
        return num * factorial(num - 1);
    }
    else {
        return 1;
    }
}

 

2. 반복문/다이나믹 프로그래밍 방식 - 스택오버 플로우 위험이 없다

더보기

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

// 스택오버플로우 안 나기 위해 재귀함수 대신 반복문으로 팩토리얼 구현
// 다이나믹 프로그램
int main()
{
    int N = 10;
    int dp[10]; // 값 저장 배열, 변수에 값을 저장
    
    dp[0] = 1;
    for (int i = 1; i < 10; i++) {
        // 점화식
     dp[i] = i * dp[i - 1]; // f(n) = n * f(n-1)
    }
    
    printf("%d! = %d", N, dp[N-1]);
    
    return 0;

}

'c' 카테고리의 다른 글

문자열  (0) 2025.11.07
포인터  (0) 2025.11.06
함수와 배열 일부  (0) 2025.11.04
반복문 (while, for)  (0) 2025.11.03
c 언어  (0) 2025.11.02