TIL 2024/7/19

Sung Joo Lee·2024년 7월 19일
0

전처리기

  • 컴파일 이전에 처리됨

  • “#”으로 시작

    • #include 은 ‘컴파일 이전에 iostream의 내용을 내 소스코드에 가져다 붙여라!’ 라고 생각하면 쉽다.

ex)

#include <iostream>
#include "myFile.h"

#ifdef
#ifndef
#define
#undef

#pragma

#define

  • 매크로를 정의하는데 사용되는 전처리기 지시어
  • Platform independency, 코드 단축 , debug 목적 등으로 활용

아래와 같은 형태로 작성을 하게 되는데

#define A B
  • 전처리 단계에서 A를 B로 치환하라는 표현식이다.
#include <iostream>

#define PI 3.14
#define AREA_OF_CIRCLE(radius) ( PI * (radius) * (radius))

int main(){
		double radius = 5.0;
		
		double area = AREA_OF_CIRCLE(radius);
		
		std::cout << "Radius:" << radius >> std::endl;
		
		retrun 0 ;
}

위의 코드를 보면 #define의 역할을 알 수 있다.

원래 따로 함수를 만들어 해당 연산(원의 넓이)을 구해야 하지만 ‘매크로’ 설정을 하여 따로 함수를 만들지 않고 AREA_OF_CIRCLE을 사용 할 수 있다.

이때 어떻게 처리되는지 과정을 알아보자

#include <iostream>

#define PI 3.14
#define AREA_OF_CIRCLE(radius) ( PI * (radius) * (radius))

int main(){
		double radius = 5.0;
		
		double area = AREA_OF_CIRCLE(radius);
		
		std::cout << "Radius:" << radius >> std::endl;
		
		retrun 0 ;
}

위의 코드를 컴파일 하면 컴파일 단계 이전에

#include <iostream>

#define PI 3.14
#define AREA_OF_CIRCLE(radius) ( PI * (radius) * (radius))

int main(){
		double radius = 5.0;
		
		double area = (3.14 * (radius) * (radius);
		
		std::cout << "Radius:" << radius >> std::endl;
		
		retrun 0 ;
}

위와 같이 매크로가 적용이 되어 위의 코드가 컴파일이된다.

주석

  • 전처리 단계에서 무시되기 때문에 동작과는 무관
  • 즉, 오브젝트 파일로 변환 되기 전에 주석은 모두 삭제 된다.

함수

  • 모든 cpp 프로그램은 하나의 main 함수를 가져야 함
  • 프로그램의 진입점 : 프로그램이 실행되면 가장 먼저 실행되는 함수
  • 리턴값 0이 올바른 프로그램 실행을 의미함

C++ 11 이전에는 main 함수는 반드시 int를 반환해야 했기 때문에 return 0; 을 명시적으로 작성해야 했지만, 이후 표준에서는 return 0;을 생략하면 컴파일러가 자동으로 추가를 시켜서 작성하지 않아도 괜찮다.

여기서 항상 기계적으로 int main()를 사용해 왔지만 왜 ‘int’가 붙는지 잘 몰라서 한번 알아보았다

  • 이는 운영체제와의 “상호작용”하기 위함이 가장 크다.

  • 프로그램이 종료가 된 이후 운영체제는 ‘종료 상태’를 통하여 프로그램의 성공 여부를 판단하는데, Linux/Unix 기반 운영체제에서 0과 이외의 정수를 통하여 판단하기 때문에 main 함수의 반환형은 “int”형이어야 한다.

namespace

코드의 “그룹화”로 이해 ( 폴더와 비슷한 개념이라고 생각해보자)

(생각해 보면 우리가 흔히 쓰는 폴더에 같은 이름의 파일이 존재할 경우 다른 이름을 쓰게 한다. 함수도 마찬가지다. namespace에 동일한 이름의 함수가 2개가 존재해서는 안된다.)

  • std :: cout
  • 충돌 방지를 위함
    • 외부 라이브러리와 구현한 소스 코드간의 이름 충돌 가능성
  • 서로 다른 namespace로 그룹화하여 충돌을 방지 할 수 있음
#include <iostream>

void function()
{
	std::cout << "Function1";
}
void function()
{
	std::cout << "Function2";
}

int main()
{
	A::function();
	function();

	return 0; //Optional

}

위의 코드를 코딩할 시 같은 이름의 함수가 존재하기 때문에 오류가 발생한다.

이때 namespace의 개념을 도입해 보자

#include <iostream>

namespace A 
{
	void function()
	{
		std::cout << "Function1";

	}
}
void function()
{
	std::cout << "Function2";
}

using namespace std;

int main()
{
	A::function();
	function();

	return 0; //Optional
}

이제 같은 이름의 함수지만 namespace가 다르게 지정이 되어있기 때문에 오류가 나지 않는다.

Using namespace

코드를 작성 하다보면 (특히 입출력이 많을 경우) 우리는 std namespace에 매번 접근해야한다.

(우리는 항상 게으르게 살 수 있도록 노력해야한다…)

특정 namespace 내의 함수들을 사용할 것 이라는 선언을 해주면 일일이 std::에 접근하지 않아도 괜찮다.

주의)

  • 남용할 경우 namespace의 기능을 상실함..
  • 보통 코딩테스트에서 std를 선언해 코드의 길이를 단축 시키지만, 실제로 프로젝트 진행시에 using namespace는 사용하지 않는다.
    • 해당 함수가 어디에 있는 함수인지 ‘구분’하기 위함인데 ‘구분’하기 어려워 진다.
#include <iostream>

using namespace std;

int main()
{
	int a;
	cout << "Enter your __";
	cin >> a;
	cout << "Good";
	
	return 0; 	
}

이제 우리가 ‘using namespace std’를 선언 했기 때문에 std::를 일일이 붙여주지 않아도 괜찮다.

Basic I/O

  • 위의 그림을 보고 “<<” 의 방향의 감각을 익혀보자!
profile
개발로그

0개의 댓글