no image
[C++] 백준 10단계 - 15894번 문제 (수학은 체육과목 입니다)
문제설명 소스코드 #include using namespace std; int main() { unsigned int N; cin >> N; cout
2023.05.13
no image
[C++] 백준 10단계 - 3009번 문제 (네 번째 점)
문제설명 소스코드 #include using namespace std; int main() { int x[3]; int y[3]; for (int i = 0; i > x[i] >> y[i]; if (x[0] == x[1]) cout
2023.05.13
no image
[C++] 백준 9단계 - 11653번 문제 (소인수분해)
문제설명 소스코드 #include using namespace std; int main() { int N; cin >> N; if (N != 1) for (int i = 2; i
2023.05.13
no image
[C++] 백준 9단계 - 2581번 문제 (소수)
문제설명 소스코드 #include using namespace std; int main() { int N, M; int sum = 0; int min = 10000; bool flag = false; bool flag2 = false; cin >> N >> M; for (int i = N; i
2023.05.12
no image
[C++] 백준 9단계 - 1978번 문제 (소수 찾기)
문제설명 소스코드 #include using namespace std; int main() { int N, input; int count = 0; bool flag = false; cin >> N; for (int i = 0; i > input; for (int j = 2; j < input; ++j) //1과 자기 자신만으로 나누어 떨어지는 1보다 큰 양의 정수. { //즉, 1과 자기 자신 외에 수로 나누어 떨어지면 소수가 아님 if (flag == true) break; // 소수가 아니라고 이미 판정되었으면 반복할 필요가 없음 if (input % j == 0) flag = true; //1과 자기 자신 외에 수로 나누어 떨어지면 flag = true } if (in..
2023.05.12
no image
[C++] 백준 9단계 - 9506번 문제 (약수들의 합)
문제설명 소스코드 #include using namespace std; int main() { int N; int count = 0; int sum = 0; while (true) { cin >> N; if (N == -1) break; int* arr = new int[N]; //동적 할당 for (int i = 1; i < N; ++i) { if (N % i == 0) //i로 나눈 나머지가 0이라면 { arr[count++] = i; //배열에 i를 저장 sum += i; //sum에 i를 더함 } } if (sum == N) //완전수라면 { cout
2023.05.12
no image
[C++] 백준 9단계 - 2501번 문제 (약수 구하기)
문제설명 소스코드 #include using namespace std; int main() { int N, K; int count = 0; cin >> N >> K; int* arr = new int[N]; for (int i = 1; i
2023.05.11
no image
[컴퓨터 구조] 메모리의 주소 공간
이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다. 주소에는 두 가지 종류가 있다. 물리 주소 : 메모리 하드웨어가 사용하는 주소 논리 주소 : CPU와 실행 중인 프로그램이 사용하는 주소 물리 주소(physical address)와 논리 주소(logical address) CPU와 실행 중인 프로그램은 현재 메모리 몇 번지에 무엇이 저장되어 있는지 다 알 수 없다(메모리에 저장된 정보는 시시각각 변하기 때문) 물리 주소 : 메모리 입장에서 바라본 주소, 정보가 실제로 저장된 하드웨어 상의 주소를 의미 논리 주소 : CPU와 실행 중인 프로그램 입장에서 바라본 주소, 실행 중인 프로그램에게 부여된 0번지부터 시작되는 주소..
2023.05.11

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
    unsigned int N;
    cin >> N;
    cout << 1 + N + (N * 2) + (N - 1);
    //맨 아래 + 맨 위 + (왼쪽 + 오른쪽) + (반씩 잘린 둘레)
    //=위 + 아래 + 옆 + 반씩 잘린 둘레 = 1 + n + 2n + (n - 1) = 4n
}

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
    int x[3]; int y[3];
    for (int i = 0; i < 3; ++i) cin >> x[i] >> y[i];
    if (x[0] == x[1]) cout << x[2] << " ";
    else if (x[0] == x[2]) cout << x[1] << " ";
    else cout << x[0] << " ";

    if (y[0] == y[1]) cout << y[2];
    else if (y[0] == y[2]) cout << y[1];
    else cout << y[0];
}

 

풀이

  • 직사각형에서 4개의 점은 같은 x좌표에 다른 y좌표 2개, 같은 y좌표에 다른 x좌표 2개 이렇게 총 4개의 점이 있다.
  • x좌표 : 세 개의 x좌표가 주어지고, 3개중 2개가 같으므로 같지 않은 하나의 x좌표를 출력한다.
  • y좌표 : 세 개의 y좌표가 주어지고, 3개중 2개가 같으므로 같지 않은 하나의 y좌표를 출력한다.

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
    int N;
    cin >> N;
    if (N != 1) for (int i = 2; i <= N; i++)  while (N % i == 0) { cout << i << endl; N /= i; }
}

 

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
	int N, M; int sum = 0; int min = 10000;
	bool flag = false; bool flag2 = false;
	cin >> N >> M;
	for (int i = N; i <= M; ++i)
	{
		for (int j = 2; j < i; ++j)
		{
			if (flag == true) break; // 이미 소수가 아닌 수로 판정되었다면 탈출
			if (i % j == 0) flag = true; // i가 j로 나누어떨어지면 소수가 아님 
		}
		if (flag == false) // i가 j로 나누어 떨어지는 수가 하나도 없다면 (소수라면)
		{
			if (i == 1) continue; // 1은 소수가 아님
			flag2 = true; // 소수가 하나라도 있다고 체크하기 위해 flag를 true로 바꿈
			sum += i; // 소수 총합
			if (i < min) min = i; // 가장 작은 소수 
		}
		else flag = false; // 플래그 초기화
	}
	(flag2 != false) ? cout << sum << endl << min : cout << "-1"; // 삼항 연산자
	
}

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
	int N, input; int count = 0;
	bool flag = false;
	cin >> N;
	for (int i = 0; i < N; ++i)
	{
		cin >> input;
		for (int j = 2; j < input; ++j) //1과 자기 자신만으로 나누어 떨어지는 1보다 큰 양의 정수.
		{ //즉, 1과 자기 자신 외에 수로 나누어 떨어지면 소수가 아님
			if (flag == true) break; // 소수가 아니라고 이미 판정되었으면 반복할 필요가 없음
			if (input % j == 0) flag = true; //1과 자기 자신 외에 수로 나누어 떨어지면 flag = true
		}
		if (input == 1) continue; //1은 소수가 아님
		else if (flag == false) ++count; //위의 반복문을 벗어날 동안 flag가 false라면 소수임
		else flag = false; //플래그 초기화
	}
	cout << count;
}

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
	int N; int count = 0; int sum = 0;
	while (true)
	{
		cin >> N;
		if (N == -1) break;
		int* arr = new int[N]; //동적 할당
		for (int i = 1; i < N; ++i)
		{
			if (N % i == 0) //i로 나눈 나머지가 0이라면
			{

				arr[count++] = i; //배열에 i를 저장
				sum += i; //sum에 i를 더함
			}
		}
		if (sum == N) //완전수라면
		{
			cout << N << " = ";
			for (int i = 0; i < count; ++i)
			{
				if (i == count - 1) cout << arr[i] << endl; //배열의 마지막은 +를 출력하면 안된다.
				else cout << arr[i] << " + "; // 배열 원소와 +를 출력한다.
			}
		}
		else cout << N << " is NOT perfect." << endl;
		cin.ignore(); //입력 버퍼 비우기
		count = 0; sum = 0; //0으로 초기화
	}
	
}

 

풀이

  • N을 입력받고 N개만큼 동적할당
  • 약수들을 배열에 저장하고 sum에 약수들을 모두 더한다.
  • 약수들의 합과 N이 같다면 완전수이므로 출력 형식대로 출력한다.
  • 마지막엔 count와 sum변수들을 0으로 초기화 시킨다. 입력버퍼 또한 비워준다.

문제설명

 

소스코드

#include <iostream>
using namespace std;
int main()
{
	int N, K; int count = 0;
	cin >> N >> K;
	int* arr = new int[N];
	for (int i = 1; i <= N ; ++i) if (N % i == 0) arr[count++] = i;
	if (count < K) cout << "0";
	else cout << arr[K - 1];
}

 

풀이

  • N개 만큼 int형 배열 동적할당
  • N을 i로 나누었을 때 나머지가 0이면 arr[count]에 i를 대입시키고 i를 증가시킴(배열에는 약수가 작은 순서대로 들어감)
  • count가 K보다 작으면 0을 출력 그렇지 않으면 arr[K - 1]을 출력 (배열의 인덱스는 0부터 시작하기 때문)

이 글은 혼자 공부하는 컴퓨터 구조 + 운영체제 (저자 : 강민철)의 책과 유튜브 영상을 참고하여 개인적으로 정리하는 글임을 알립니다.


주소에는 두 가지 종류가 있다.

  • 물리 주소 : 메모리 하드웨어가 사용하는 주소
  • 논리 주소 : CPU와 실행 중인 프로그램이 사용하는 주소

 

물리 주소(physical address)와 논리 주소(logical address)

  • CPU와 실행 중인 프로그램은 현재 메모리 몇 번지에 무엇이 저장되어 있는지 다 알 수 없다(메모리에 저장된 정보는 시시각각 변하기 때문)
  • 물리 주소 : 메모리 입장에서 바라본 주소, 정보가 실제로 저장된 하드웨어 상의 주소를 의미
  • 논리 주소 : CPU와 실행 중인 프로그램 입장에서 바라본 주소, 실행 중인 프로그램에게 부여된 0번지부터 시작되는 주소를 의미

만약 현재 메모리에 메모장, 게임, 웹 브라우저가 적재되어 있다고 가정하면 이러한 프로그램들은 다른 프로그램들이 메모리 몇 번지에 저장되어 있는지(물리주소) 굳이 알 필요가 없다.

그래서 프로그램들은 모두 물리 주소가 아닌 0번지부터 시작하는 자신만을 위한 주소인 논리 주소를 가지고 있다.

예를 들어 10번지라는 주소는 메모장에도, 게임에도, 웹 브라우저에도 논리 주소로써 존재할 수 있다.

 

하지만 CPU가 이해하는 주소가 논리 주소라고 해도 CPU가 메모리와 상호작용하려면 논리 주소와 물리 주소 간의 변환이 이루어져야 한다.

 

논리 주소는 물리 주소로 변환 되려면 메모리 관리 장치(MMU)라는 하드웨어에 의해 수행된다.

 

 

MMU는 CPU가 발생 시킨 논리 주소에 베이스 레지스터 값을 더해 논리 주소를 물리 주소로 변환한다.

베이스 레지스터
베이스 레지스터 값에는 프로그램의 시작주소(즉, 물리 주소상의 시작주소) 값이 담긴다.

예를 들어 현재 베이스 레지스터에 15000이 저장 되어 있고 CPU가 발생시킨 논리 주소가 100번지라면 이 논리 주소는 아래 그림처럼 물리 주소 15100번지(15000+100)로 변환된다.

 

만약 베이스 레지스터에 45000이 저장되어 있고 CPU가 발생시킨 논리 주소가 100번지라면 이 논리 주소는 물리 주소 45100(45000+100)번지로 변환된다.

 

  • 베이스 레지스터는 프로그램의 가장 작은 물리 주소, 즉 프로그램의 첫 물리 주소를 저장하는 셈이고,
  • 논리 주소는 프로그램의 시작점으로부터 떨어진 거리인 셈이다.

 


 

메모리 보호 기법

메모장 프로그램의 물리 주소가 1000번지부터 1999번지, 인터넷 브라우저 프로그램의 물리 주소가 2000번지부터 2999번지, 게임 프로그램의 물리 주소가 3000번지부터 3999번지라고 가정하면, CPU가 메모장 논리 주소 1500번지에 100을 저장하라고 명령을 내렸다면 이 명령어는 실행 되어서는 안 된다.

왜냐하면 메모장 프로그램의 논리 주소 범위는 0부터 999까지이기 때문이다.

이러한 명령어가 실행되면 애꿎은 인터넷 브라우저의 논리 주소상 500번지의 데이터만 바뀌게 될 것이다.

이렇게 다른 프로그램의 영역을 침범할 수 있는 명령어는 위험하기 때문에 논리 주소 범위를 벗어나는 명령어 실행을 방지하고 실행 중인 프로그램이 다른 프로그램에 영향을 받지 않도록 보호할 방법이 필요하다.

이는 한계 레지스터가 담당한다.

베이스 레지스터가 실행 중인 프로그램의 가장 작은 물리 주소를 저장한다면, 한계 레지스터는 논리 주소의 최대 크기를 저장한다.

즉, 프로그램의 물리 주소 범위는 베이스 레지스터 값 이상, 베이스 레지스터 값 + 한계 레지스터 값 미만이 된다.

 

한계 레지스터

  • 프로그램의 영역을 침범할 수 있는 명령어의 실행을 막음
  • 베이스 레지스터가 실행 중인 프로그램의 가장 작은 물리 주소를 저장한다면, 한계 레지스터는 논리 주소의 최대 크기를 저장
  • 베이스 레지스터 값 <= 프로그램의 물리 주소 범위 < 베이스 레지스터 + 한계 레지스터 값

 

CPU는 메모리에 접근하기 전에 접근하고자 하는 논리 주소가 한계 레지스터보다 작은지를 항상 검사한다. 만약 CPU가 한계 레지스터보다 높은 논리 주소에 접근하려고 하면 인터럽트(트랩)를 발생시켜 실행을 중단한다.

 

이러한 방식으로 실행 중인 프로그램의 독립적인 실행 공간을 확보하고 하나의 프로그램이 다른 프로그램을 침범하지 못하게 보호할 수 있다.