본문 바로가기
카테고리 없음

C 언어 기본] 반복문

by redcubes 2024. 3. 15.

목차

A. while, for, do while

B. 반복문 활용

C. 정리 확인

A. 반복문

____1. while

#include <stdio.h>

int main(void)
{
	int a = 1;               // 변수를 선언하고 곱셈을 하기 위해 1로 초기화

	while (a < 10)           // ① a가 10보다 작으므로 조건식은 참
	{
		a = a * 2;           // ② a에 2를 곱해 a에 다시 저장
	}
	printf("a : %d\n", a);   // a 값 출력

	return 0;
}

____2. for

#include <stdio.h>

int main(void)
{
	int a = 1;                   // 변수를 선언하고 1로 초기화
	int i;                       // 반복 횟수를 세기 위한 변수

	for (i = 0; i < 3; i++)      // ① i는 0으로 초기화된 후에 ② 3보다 작은 동안(i < 3)
	{                            // ③ 하나씩 증가하면서(i++)
		a = a * 2;               // 실행문을 실행
	}
	printf("a : %d\n", a);       // for문을 빠져나오면 a 값 출력

	return 0;
}

____3. 

#include <stdio.h>

int main(void)
{
	int a = 1;                // 변수를 선언하고 1로 초기화

	do                        // 반복문 시작 위치
	{
		a = a * 2;            // a의 값을 2배로 늘린다.
	} while (a < 10);         // a가 10보다 작으면 9행을 반복
	printf("a : %d\n", a);    // 반복이 끝난 후 a 값 출력

	return 0;
}

 

B. 반복문 활용

____1. 중첩

#include <stdio.h>

int main(void)
{
  int i, j;                    

  for (i = 0; i < 10; i++)     
  {
    for (j = 0; j < i; j++)  
    {
      printf("*");     
    }
    printf("\n");      
  }

  return 0;
}
*
**
***
****
*****
******
*******
********
*********

주의점: 제어변수 같으면 영향을 줌.

구구단 출력

____2. break

#include <stdio.h>

int main(void)
{
	int i;							// 반복 횟수를 세기 위한 제어 변수
	int sum = 0;					// 1부터 10까지의 합을 누적할 변수

	for (i = 1; i <= 10; i++)		// i는 1부터 10까지 증가하면서 10번 반복
	{
		sum += i;					// i 값을 sum에 누적
		if (sum > 30) break;		// 누적한 값이 30보다 크면 반복문을 끝낸다.
	}
	printf("누적한 값 : %d\n", sum);
	printf("마지막으로 더한 값 : %d\n", i);

	return 0;
}

____3. continue

-

for (i = 0; i<100,i++)
{
	if ((i%3)==0)
    {
    continue;
    }
    sum+=1;
}

 

C. 정리 확인 

____1. 요약정리

- 중첩 반복문은 반복문의 실행문으로 반복문을 갖는다.(한 개의 실행문으로 인식해서 중괄호 없을 수 있으나, 중괄호 써라.)
break, continue는 여기도 있다.

____2 . 확인문제

출처: 혼자 공부하는 C언어 기본편

#include <stdio.h>
int main() {
    unsigned int n = 4;

    for (int i = 0; i < n+1; i++) {
        for (int j = 0; j < n+1; j++) {
            if (i == j || i + j == 4) {
                printf("*");
            } else {printf(" ");}
        }
        printf("\n");
    }
    return 0;
}

https://www.acmicpc.net/problem/2444

 

2444번: 별 찍기 - 7

첫째 줄부터 2×N-1번째 줄까지 차례대로 별을 출력한다.

www.acmicpc.net

반복문을 연습하기 위해 별을 찍어 보았다.

#include <stdio.h>
int main() 
{ 
    unsigned int n;
    scanf("%u", &n);

    for (int u = 1; u < n; u++)
        {
            for (int j = 0; j < n-u; j++)
                {
                    printf(" ");                    
                }
            for (int j = 0; j < 2*u-1; j++)
                {
                    printf("*");
                }
            printf("\n");
        }
    for (int d = 0; d < n; d++)
        {
            for (int j = 0; j < d; j++)
                {
                    printf(" ");
                }
            for (int j = 0; j < 2*(n-d)-1; j++)
                {
                    printf("*");
                }
            printf("\n");
        }
            
        
    return 0; 
}

 

5
    *
   ***
  *****
 *******
*********
 *******
  *****
   ***
    *

____3. 궁금한 점

- 반복문의 제어변수와 일반적인 변수는 어떻게 다른가?
gpt와 이야기해 보았다.

C 언어에서 반복문의 제어변수와 일반적인 변수는 메모리 세그먼트 측면에서 어떻게 다른가?

C 언어에서 반복문의 제어변수와 일반적인 변수는 기본적으로 메모리 세그먼트 측면에서 큰 차이가 없습니다. C 언어 프로그램이 실행될 때, 변수는 메모리의 다양한 세그먼트에 할당될 수 있습니다. 이 세그먼트들은 텍스트(Text), 데이터(Data), 스택(Stack), 힙(Heap) 등으로 구분됩니다.

1. 텍스트 세그먼트: 프로그램의 실행 코드가 저장되는 곳입니다. 여기에는 함수, 조건문, 반복문 등 프로그램을 구성하는 명령어들이 저장됩니다.

2. 데이터 세그먼트: 초기화된 전역 변수와 정적 변수(static variables)가 저장되는 곳입니다. 이 세그먼트는 더 세분화되어 초기화된 데이터 세그먼트와 초기화되지 않은(또는 BSS(Block Started by Symbol) 세그먼트) 데이터 세그먼트로 나뉩니다.

3. 스택 세그먼트: 함수의 지역 변수와 함수 호출 정보가 저장되는 곳입니다. 스택은 LIFO(Last In, First Out) 방식으로 작동합니다. 함수 호출 시 생성되는 지역 변수들과 반복문의 제어변수(지역 범위에 선언된 경우)는 이 세그먼트에 저장됩니다.

4. 힙 세그먼트: 동적으로 할당된 메모리(예: `malloc`, `calloc`, `realloc` 함수를 사용하여 할당된 메모리)가 저장되는 곳입니다. 프로그래머가 직접 관리해야 합니다.

반복문의 제어변수가 함수 내부에서 선언된 경우, 일반적으로 스택 세그먼트에 저장됩니다. 이는 함수 내의 다른 지역 변수와 동일합니다. 반면에, 전역 범위에서 선언된 반복문의 제어변수나 일반적인 변수는 데이터 세그먼트에 저장됩니다.

결론적으로, 변수가 반복문의 제어변수인지 아닌지보다는 그 변수가 어디에 선언되었는지(지역변수인지 전역변수인지, 정적변수인지 등)가 메모리 세그먼트에 할당되는 위치를 결정하는 주된 요소입니다.

반복문의 제어변수가 반복문 블록 내부에서 선언되는 경우, 그 변수의 범위(scope)는 해당 반복문 블록으로 제한됩니다. 이는 변수의 가시성과 생명주기를 관리하는 프로그래밍 언어의 범위 규칙 때문입니다.

C 언어에서 변수의 범위는 그 변수가 선언된 위치에 따라 결정됩니다. 만약 변수가 함수 내부의 특정 블록(예를 들어, for, while, if 블록 등) 안에서 선언되었다면, 그 변수는 그 블록 내부에서만 접근이 가능하고, 블록 외부에서는 접근할 수 없습니다. 이러한 변수를 "블록 범위를 가진 지역 변수"라고 합니다.

예를 들어, 다음과 같은 C 언어 코드를 봅시다:

for (int i = 0; i < 10; i++) {
    // 반복문 내부에서 i는 접근 가능
}
// 여기에서는 i에 접근할 수 없음

위 코드에서 'int i = 0;'이라는 선언은 'for' 반복문의 블록 안에서 이루어졌기 때문에, 'i'의 범위는 그 반복문의 블록으로 제한됩니다. 따라서 반복문 외부에서는 'i'에 대한 접근이 불가능합니다.

이런 방식으로 변수의 범위를 제한함으로써, 프로그램의 다른 부분에서 동일한 이름의 변수를 사용할 때 발생할 수 있는 이름 충돌을 방지하고, 프로그램의 가독성과 유지보수성을 향상시킬 수 있습니다. 또한, 블록 범위를 가진 지역 변수는 그 블록의 실행이 끝나면 메모리에서 해제되어, 메모리 사용 효율성을 높일 수 있습니다.

스코프 법칙은 컴파일러가 제공하는거지?

네, 맞습니다. 스코프 법칙은 컴파일러가 제공하는 기능의 일부입니다. 스코프(scope)는 프로그래밍 언어에서 변수나 함수와 같은 식별자가 프로그램 내에서 유효한 범위를 정의합니다. 컴파일러는 소스 코드를 분석할 때 이러한 스코프 규칙을 적용하여 각 식별자의 가시성과 생명주기를 관리합니다.

컴파일 과정 중에 컴파일러는 다음과 같은 작업을 수행합니다:

1. 식별자의 선언 위치 파악: 컴파일러는 변수, 함수 등의 식별자가 선언된 위치를 찾아 그 범위를 결정합니다. 이 범위는 식별자가 접근 가능한 코드 영역을 나타냅니다.

2. 식별자의 가시성 검사: 컴파일러는 코드의 각 부분에서 사용된 식별자가 해당 위치에서 접근 가능한지 검사합니다. 이 과정에서 스코프 규칙을 적용하여 식별자가 유효한 범위 내에 있는지 확인합니다.

3. 이름 충돌 해결: 같은 이름을 가진 식별자가 다른 스코프에서 선언되었을 경우, 컴파일러는 스코프 규칙을 사용하여 어느 식별자를 참조하는지 결정합니다.

스코프 규칙을 통해 컴파일러는 코드 내에서 변수나 함수 등의 식별자가 어디서, 언제 사용될 수 있는지를 정확히 관리할 수 있습니다. 이는 프로그램의 정확성을 보장하고, 변수 이름 충돌로 인한 오류를 방지하는 데 중요한 역할을 합니다. 따라서 스코프는 프로그램의 구조를 명확하게 하고, 코드의 가독성 및 유지보수성을 향상시키는 데 기여합니다.

스코프 규칙을 GC로 볼 수 없나?

스코프 규칙과 가비지 컬렉션(Garbage Collection, GC)은 서로 다른 개념입니다. 각각은 프로그램의 메모리 관리와 관련된 중요한 역할을 하지만, 작동 원리와 목적에서 차이가 있습니다.

### 스코프 규칙

- 스코프 규칙은 프로그램 내에서 변수나 함수와 같은 식별자의 가시성과 생명주기를 정의합니다. 즉, 어떤 식별자가 프로그램의 어떤 부분에서 접근 가능한지를 결정하는 규칙입니다.
- 스코프는 컴파일 시간에 결정됩니다. 컴파일러는 코드를 분석하면서 각 식별자의 스코프를 결정하고, 이를 기반으로 식별자의 가시성을 관리합니다.
- 스코프 규칙은 주로 프로그램의 정확성을 보장하고, 이름 충돌을 방지하는 데 목적이 있습니다.

### 가비지 컬렉션(GC)

- 가비지 컬렉션은 동적으로 할당된 메모리 중에서 더 이상 프로그램에서 사용되지 않는 부분을 자동으로 찾아서 해제하는 과정입니다. 이는 주로 런타임 시에 발생합니다.
- GC의 주 목적은 사용되지 않는 메모리를 자동으로 회수하여 메모리 누수를 방지하고, 프로그램의 메모리 효율성을 높이는 것입니다.
- 가비지 컬렉션은 주로 관리되는 런타임 환경에서 사용됩니다. 예를 들어, Java, .NET과 같은 환경에서는 GC가 중요한 메모리 관리 기법 중 하나입니다.

### 결론

따라서 스코프 규칙은 컴파일러가 코드의 구조를 분석하여 식별자의 가시성을 결정하는 규칙이며, 가비지 컬렉션은 런타임 시 메모리 관리를 위해 사용되는 기술입니다. 둘 다 메모리 관리와 관련된 중요한 역할을 하지만, 그 목적과 작동 방식에서는 큰 차이가 있으므로 스코프 규칙을 가비지 컬렉션으로 볼 수는 없습니다.