P_Squirrel
Squirrel Hack
P_Squirrel
전체 방문자
오늘
어제
  • 분류 전체보기 (434)
    • Wargame(Web) (176)
      • Webhacking.kr Writeup (58)
      • DreamHack Writeup (67)
      • Lord of SQLInjection (40)
      • Websec.fr (2)
      • Webgoat (1)
      • G04T war (7)
    • Wargame(Pwnable) (95)
      • DreamHack Writeup (69)
      • pwnable.xyz Writeup (20)
      • G04T war (6)
    • Wargame(Reversing) (26)
      • DreamHack Writeup (26)
    • Wargame(crypto) (7)
      • DreamHack Writeup (7)
    • Wargame(DigitalForensic) (41)
      • CTF-D Writeup (28)
      • DreamHack Writeup (6)
      • Suninatas Writeup (7)
    • Wargame(misc) (4)
      • DreamHack Writeup (4)
    • DreamHack CTF (21)
    • BDSec CTF (5)
    • AmateursCTF (2)
    • ångstrom CTF (6)
    • L3ak CTF (1)
    • Hspace war (1)
    • Reference (42)
      • Language_Study (10)
      • Pwnable_Study (24)
      • Web Hacking_Study (3)
      • Linux (2)
      • Windows Kernel (1)
    • 자격증 공부 (2)
      • 정보처리기사 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 문

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
P_Squirrel
Reference/Language_Study

[C++] 2. C++ typeid, endl 과 \n 차이

Reference/Language_Study

[C++] 2. C++ typeid, endl 과 \n 차이

2024. 3. 19. 14:37

본글은 최근에 Pwnable 문제중 C언어, Python뿐만 아니라

C++로 이루이진 문제를 접하는 경우가 많아져서 Python, Java와 다른 C++만의 문법이나

차이점등을 정리하기 위해 작성한 글입니다.

틀린부분이 있다면 댓글로 알려주시기 바랍니다.

 

(예시 코드등은 TCP 스쿨의 자료를 참고했습니다.)

https://www.tcpschool.com/cpp/intro

 


C++ type 확인

C++ 에서도 Java나 Python 처럼 객체의 타입에 관한 정보를 확인 해야 할 때가 있다.

이때 C++에서 사용되는 문법이 typeid 이다.

typeid(표현식)

 

이 typeid는 다른 문법에서 처럼 타입을 확인할 수 있게 해주는 기능만 있는 것이 아닌

name 이라는 멤버 함수를 추가로 확인이 가능한데

이는 클래스의 이름을 문자열로 치환해 반환해준다.

(단, 컴파일러 제작사마다 다르기때문에 동일한 문자열을 반환할것이라고 추측해서는 안됨)

 

예시 코드를 보면

#include <iostream>

using namespace std;

int main(void)
{
	cout << typeid(int).name() << endl; // 기본 자료형
	cout << typeid(type_info).name() << endl; // 클래스
	cout << typeid(main).name() << endl; // 함수
	cout << typeid(cout).name() << endl; // 객체
}

// return 결과
int
class type_info
int __cdecl(void)
class std::basic_ostream<char,struct std::char_traits >

int, type_info, main, cout의 name을 확인하는데

int의 경우에는 기본 자료형이기때문에 int를

클래스의 경우 해당 클래스의 이름과 class라는 타입을

cout는 헤더파일 iostream의 정보를 가져오는 것과 class타입임을 확인 할 수 있다.

 

이러한 정보는 코드를 작성하다 형변환이 필요할때 해당 클래스가 맞는지 확인하기

편리하고 부모자식간의 형변환이 가능하기에 해당 정보가 필요하다.

class A {
public:
	virtual void vf() {}
};
class B : public A {
public:
	bool b;
};
class C : public A {
public:
	int c;
};

void memberPrint(A* a)
{
	if (typeid(B) == typeid(*a)) {			//B 클래스인지 검사
		B* b = (B*)a;						//자식클래스로 강제 형변환 이지만 안전이 보장됨
		cout << typeid(b->b).name() << endl;
	}
	else if (typeid(C) == typeid(*a)) {		//C 클래스인지 검사
		C* b = (C*)a;						//자식클래스로 강제 형변환 이지만 안전이 보장됨
		cout << typeid(b->c).name() << endl;
	}
}

int main() {
	A* a[] = { &B(), &C() };
	memberPrint(a[0]);
	memberPrint(a[1]);
}

위의 코드처럼 typeid를 조건문으로 넣어 해당 클래스를 확인후

형변환을 하는 코드를 구성할 수 있어 type을 확인할 수 있는 typeid()는 유용하게 사용할 수 있다.

 


C++ endl 과 \n 차이

C나 Python에서는 \n 은 줄바꿈으로써 print(), printf()등에서 줄을 바꿀때 사용한다.

C++에서 또한 \n을 사용할 수 있지만,

대부분의 C++ 코드에서 문자열의 끝에는 std::endl을 사용하는 것이 보편적이다.

 

C에서 이미 익숙하고 python으로 까지 포괄적으로 사용되는 \n 대신

왜 endl을 사용하는지 이유를 알아보았다.

 

한마디로 정리하면 입출력버퍼 때문에 endl을 사용한다.

출처: TCP 스쿨

 

위의 이미지를 보면 버퍼를 사용하는 입력의 경우 입력값을 버퍼에 쌓아두고

이를 한번에 전송한다.

 

이때 전송하는 조건을 보면 개행문자가 나타나거나, 버퍼가 가득차는 경우이다.

C++ 에서는 이 개행문자의 역할을 endl이 하는 것이다.

(이외에도 fflush()를 사용하는 경우가 있는데

pwnable CTF 문제에서 해당 함수에 관한 취약점 문제를 풀어본적이 있다.)

 

endl을 사용하는 경우와 사용하지 않는 경우 코드를 사용하면 이해가 훨씬 간단하다.

int main(void)
{
    std::cout << "hello" << std::endl;
    sleep(5);
    return (0);
}

int main(void)
{
    std::cout << "hello";
    sleep(5);
    return (0);
}

두 코드를 놓고 개발자의 입장에서 생각해보면

개발자가 원하는 코드의 흐름은

hello를 출력한뒤 5초를 기다리는 것이다.

 

첫번째 코드인 endl을 사용하는 경우에는 hello가 출력한뒤 5초후 종료되어 정상적으로 작동한다.

반면에 endl을 사용하지 않은 코드의 경우 5초가 흐른뒤 hello를 출력하고 종료된다.

 

이는 hello문자열이 버퍼에 들어갔으나 개행문자가 없었고,

버퍼또한 꽉차지 않았기 때문에 발생하는 문제이다.

 

\n가 hello 중간에 들어가도 마찬가지 이다.

\n은 개행문자가 아닌 줄바꿈의 역할을 하는 문자이기에

버퍼를 비우지 않는다.

 

그러나 버퍼를 비우는 것이 해당 문자열의 끝으로 보고 줄바꿈이 진행되기에

endl을 줄바꿈으로 사용할 수 있다고도 한다.

 

하지만, 백준등에서 타임아웃등의 문제로 빠른 처리를 요구하는 경우에는 버퍼를

비우지 않고 줄바꿈을 진행하는 \n이 훨씬 빠르기 때문에

즉시 출력해야하는 경우가 아니라면 \n을 사용하는 것으로 시간을 줄이는 것이 가능하다.

 

정리하면, 두개 모두 각 환경에 따라 필요할 수가 있으니

두 개의 차이점을 숙지하고 구분해 사용할 수 있어야 한다.

 

 


Reference

1. https://velog.io/@kdi2514/Modern-c-typeid

2. https://www.tcpschool.com/cpp/cpp_operator_cpp

3. https://yechoi.tistory.com/48

'Reference > Language_Study' 카테고리의 다른 글

[C++] 4. C++ 참조자(reference), 소멸자(destructor)  (2) 2024.03.25
[C++] 3. C++ new()와 delete()  (0) 2024.03.22
[C++] 1. C++ nullptr, namespace  (0) 2024.03.18
명품 JAVA 에센셜 6장 실습문제  (0) 2022.06.14
상속 문제(Unit)  (0) 2022.06.07
  • C++ type 확인
  • C++ endl 과 \n 차이
  • Reference
'Reference/Language_Study' 카테고리의 다른 글
  • [C++] 4. C++ 참조자(reference), 소멸자(destructor)
  • [C++] 3. C++ new()와 delete()
  • [C++] 1. C++ nullptr, namespace
  • 명품 JAVA 에센셜 6장 실습문제
P_Squirrel
P_Squirrel
Squirrel HackP_Squirrel 님의 블로그입니다.

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.