C++에서는 배열 전체를 그대로 함수의 인수(argument)로 전달하는 것이 허용되지 않습니다. 대신, 인덱스 없이 배열의 이름만 지정하면 배열을 가리키는 포인터를 함수에 전달할 수 있습니다.1차원 배열을 함수의 인수로 전달하고 싶다면, 함수의 형식 매개변수(formal parameter)를 아래 세 가지 방법 중 하나로 선언해야 합니다. 세 가지 선언 방식 모두 컴파일러에게 정수형 포인터를 전달받는다는 동일한 의미를 전달하기 때문에 결과적으로 같은 방식으로 동작합니다.배열을 함수에 전달하는 3가지 방법1. 포인터 형태의 매개변수
C++에서 정의되지 않은 동작(Undefined Behavior, UB)이란 표준이 동작을 규정하지 않아 컴파일러가 임의로 처리할 수 있는 상황을 말합니다. UB가 발생하면 프로그램이 정상적으로 실행될 수도 있고, 충돌하거나 예측 불가능한 결과를 낳을 수도 있습니다. 더 위험한 점은 최적화 과정에서 컴파일러가 이러한 상황을 전제에 포함하지 않기 때문에, 겉보기에는 멀쩡해 보이는 코드도 의도치 않게 깨질 수 있다는 것입니다.다음은 C++ 프로그래밍에서 가장 흔하게 나타나는 정의되지 않은 동작의 원인들입니다. 모두 C++ 표준에서 명시
C++에서는 배열 전체를 함수의 인수로 직접 전달할 수 없습니다. 다만, 인덱스를 생략한 배열 이름을 지정하면 배열에 대한 포인터를 전달할 수 있습니다. 2차원 배열을 함수에 전달하는 방법은 크게 세 가지가 있으며, 각각의 방법과 특징을 아래에서 자세히 살펴보겠습니다.방법 1. 2차원 배열의 열 크기 지정하기함수 매개변수에서 행(row) 크기는 생략할 수 있지만, 열(column) 크기는 반드시 명시해야 합니다. 컴파일러가 배열 요소의 메모리 위치를 계산하려면 열 크기 정보가 필요하기 때문입니다.void processArr(int
C++에는 여러 종류의 타입 캐스트(type cast)가 있으며, 각각의 용도와 안전성 수준이 다릅니다. 잘못된 캐스트를 사용하면 런타임 오류나 예기치 않은 동작으로 이어질 수 있으므로, 상황에 맞는 올바른 캐스트를 선택하는 것이 중요합니다.1. static_caststatic_cast는 가장 일반적인 타입 변환에 사용되는 캐스트입니다. 컴파일 타임에 타입 검사를 수행하며, 암시적 타입 변환이 일어나는 경우에도 내부적으로 이 캐스트가 관여합니다. 물론 개발자가 명시적으로 호출할 수도 있습니다.float를 int로 변환하거나, cha
C++에서 정방향 선언(forward declaration)은 클래스의 실제 정의보다 앞서 클래스의 이름만 미리 알려주는 기법입니다. 정방향 선언을 사용하면 선언 이후에 오는 코드들은 Person이라는 이름의 클래스가 존재한다는 사실을 인지하게 되며, 컴파일러는 해당 이름이 사용되는 것을 보아도 오류 없이 통과시킵니다. 클래스의 실제 정의는 컴파일 이후 링커(linker)가 찾아 연결하게 됩니다.정방향 선언 예제class Person; // 정방향 선언 void myFunc(Person p1) { // ... } cla
전역 변수는 왜 문제가 될까?전역 변수의 사용은 C++뿐만 아니라 모든 프로그래밍 언어에서 가급적 피해야 합니다. 그 이유는 전역 변수가 전역 네임스페이스(namespace)를 오염시키고, 프로그램의 어느 파일에서든 접근하고 수정할 수 있기 때문에 규모가 큰 프로젝트에서는 매우 성가신 버그를 유발할 수 있기 때문입니다.전역 변수가 나쁜 이유코드의 어느 부분에서든 전역 변수를 변경할 수 있기 때문에, 가능한 모든 사용 지점을 기억하거나 추론하기가 어렵습니다.전역 변수에는 접근 제어(access control)가 존재하지 않습니다. 프
결론부터 말하면: C++에서는 사실상 차이가 없습니다C++에서는 struct와 typedef struct 사이에 실질적인 차이가 없습니다. 그 이유는 C++에서 모든 struct, union, enum, class 선언이 마치 암시적으로 typedef된 것처럼 동작하기 때문입니다. 다만, 같은 이름을 가진 다른 선언에 의해 이름이 가려지지 않는 경우에 한정됩니다.즉, C++에서는 다음과 같이 구조체 이름을 곧바로 타입처럼 사용할 수 있습니다.struct Point { int x; &
C++ 프로그램 내부에서 운영체제의 셸 명령을 실행하고 그 결과(출력)를 코드 안에서 직접 받아와야 하는 경우가 종종 있습니다. 예를 들어 ls 같은 시스템 명령의 결과를 문자열로 가져와 가공해야 할 때가 대표적입니다.이럴 때 POSIX 계열 시스템(Linux, macOS 등)에서는 popen과 pclose 함수를 사용하면 간단하게 해결할 수 있습니다.popen과 pclose란?popen() 함수는 파이프(pipe)를 생성하고, 프로세스를 포크(fork)한 뒤, 지정한 명령을 셸(shell)을 통해 실행합니다. 이렇게 열린 파이프는
C++에서는 STL에서 제공하는 std::sort 함수를 사용해 사용자 정의 객체(custom object)로 이루어진 벡터를 손쉽게 정렬할 수 있습니다. std::sort는 오버로드된 형태 중 하나로 (first, last, comparator) 세 가지 인자를 받는 버전을 제공합니다.first: 정렬할 범위의 첫 번째 요소를 가리키는 반복자(iterator)last: 정렬할 범위의 마지막 다음 요소를 가리키는 반복자comparator: 컨테이너를 어떤 기준으로 정렬할지 결정하는 술어(predicate) 함수예제 코드다음은 C++
정의되지 않은 동작(Undefined Behavior)이란? 정의되지 않은 동작(Undefined Behavior, UB)은 컴파일러나 운영체제처럼 프로그램을 구현하는 쪽과 컴퓨터 자신에게 결과에 대해 신경 쓰지 않고 자유롭게 동작할 수 있는 권한을 부여하는 개념입니다. 즉, C++ 표준이 특정 상황에서의 결과를 규정하지 않기 때문에, 그 상황에서 프로그램이 어떻게 동작하든 표준 차원에서는 잘못된 것으로 간주하지 않습니다. 세그먼테이션 오류는 왜 항상 발생하지 않을까? 흥미로운 점은 세그먼테이션 오류(segmentation fau
C++에서 출력할 때 개발자들이 가장 자주 혼동하는 부분 중 하나가 바로 std::endl과 \n의 차이입니다. 두 표현 모두 줄바꿈을 수행하지만, 내부적으로 동작하는 방식에 중요한 차이가 있습니다.기본 동작의 차이\n은 단순히 개행 문자를 출력합니다. 이때 개행 문자는 운영체제에 맞는 형태로 자동 변환됩니다. 예를 들어 Windows에서는 \r\n(캐리지 리턴 + 라인 피드)으로 처리되어 플랫폼 간 호환성을 유지합니다.반면 std::endl은 줄바꿈을 출력하는 것에 더해 출력 스트림을 즉시 플러시(flush)합니다. 즉, 버퍼에
C++ 프로그래밍을 하다 보면 정수(int) 값을 문자열(string)로 변환해야 하는 상황이 자주 발생합니다. 예를 들어 숫자와 텍스트를 함께 출력하거나, 파일·네트워크로 데이터를 전송할 때 그렇습니다. 대표적인 변환 방법으로는 C 언어의 itoa 함수를 사용하는 방법과, C++11부터 표준에 추가된 to_string 함수를 사용하는 방법이 있습니다.1. itoa 함수를 사용한 변환C 언어에서 제공하는 itoa 함수를 활용하면 정수를 문자열로 바꿀 수 있습니다. 다음 예제를 살펴보세요.#include<iostream>#
C++에서 explicit 키워드는 생성자가 암시적(implicit) 타입 변환을 수행하지 않도록 명시적으로 지정할 때 사용됩니다. 이를 통해 개발자가 의도하지 않은 자동 형 변환으로 인한 버그를 사전에 방지할 수 있습니다.암시적 변환의 문제점먼저 다음과 같은 클래스가 있다고 가정해 보겠습니다.class Foo { public: Foo(int n); // Foo 객체에 n바이트를 할당 Foo(const char *p); // char *p로 객체를 초기화 };이 상태에서 다음과 같은 코드를 작성하면 어떻게 될까요?Fo
생성자에서 가상 함수 호출의 문제점생성자나 소멸자 내부에서 가상 함수를 호출하는 것은 매우 위험하며, 가급적 피하는 것이 좋습니다. 그 이유는 호출된 가상 함수가 파생 클래스(Derived)의 버전이 아니라 기반 클래스(Base)의 버전으로 실행되기 때문입니다.C++에서는 모든 클래스가 자신의 생성 과정에 진입하기 전에 먼저 자신만의 가상 메서드 테이블(vtable)을 구성합니다. 따라서 생성자 안에서 가상 메서드를 호출하면 기반 클래스의 가상 메서드가 실행됩니다. 만약 해당 계층에 구현이 전혀 존재하지 않는다면 순수 가상 함수 호
C++에서 코드를 헤더 파일(.h)과 소스 파일(.cpp)로 나누는 가장 큰 이유는 인터페이스(선언)와 구현(정의)을 분리하기 위해서입니다. 이러한 구조는 자바의 인터페이스 개념과 유사하게, 클래스가 외부에 공개하는 부분과 내부 동작 방식을 명확히 구분해 줍니다.헤더 파일은 무엇(What)을 선언합니다헤더 파일에는 클래스나 함수가 무엇을 할 수 있는지, 즉 해당 클래스의 API가 선언됩니다. 어떤 메서드가 존재하고, 어떤 매개변수와 반환 타입을 갖는지 등 외부에서 알아야 할 정보만 담고 있습니다..cpp 파일은 어떻게(How)를 정
C++ 표준 라이브러리만으로는 개행(Enter)을 기다리지 않고 키 입력을 즉시 읽는 이식 가능한(portable) 방법이 존재하지 않습니다. 운영체제마다 터미널의 동작 방식이 다르기 때문에, 플랫폼별로 다른 접근 방식을 사용해야 합니다.Windows에서 구현하기 — conio.h의 getch() 함수Windows에서는 conio(Console I/O) 라이브러리에서 제공하는 getch() 함수를 사용하면 됩니다. 이 함수는 사용자가 누른 문자를 버퍼링 없이 바로 반환해 줍니다.예제 코드#include<iostream>
C++에서 문자열을 정수(int)로 변환하는 방법은 크게 두 가지가 있습니다. 하나는 문자열 스트림(stringstream)을 활용하는 방법이고, 다른 하나는 C++11부터 도입된 stoi() 계열 변환 함수를 사용하는 방법입니다. 각 방법의 특징과 예제 코드를 살펴보겠습니다. 1. stringstream을 이용한 변환 stringstream은 문자열을 입력 스트림처럼 다룰 수 있게 해주는 클래스입니다. 문자열에서 숫자를 추출할 때 유용하며, 변환 실패 여부를 확인하는 에러 검사 로직을 함께 작성하면 더욱 안전하게 사용할 수 있습
C++에서 std::string 객체를 C 스타일 문자열인 const char* 또는 char*로 변환해야 하는 경우가 자주 있습니다. 상황에 따라 적합한 변환 방법이 다르므로, 각 방법과 주의 사항을 예제와 함께 살펴보겠습니다. c_str() 메서드로 const char* 얻기 string 클래스가 제공하는 c_str() 메서드를 사용하면 문자열 내용을 담고 있는 const char* 포인터를 손쉽게 얻을 수 있습니다. 반환되는 포인터는 널 종료 문자(\0)를 포함하며, 원본 문자열이 수정되거나 소멸되면 해당 포인터는 더 이상 유
C++에서 cout 출력 스트림은 다양한 조작자(manipulator)를 지원합니다. 이 조작자들을 활용하면 cout 객체에 직접 정밀도(precision)를 설정하고, fixed 형식 지정자를 함께 사용해 소수점 아래 자릿수를 고정된 형태로 출력할 수 있습니다.일반적으로 cout은 기본적으로 유효 숫자 6자리까지만 출력하기 때문에, double 타입이 가진 전체 정밀도를 확인하려면 별도의 설정이 필요합니다. 이때 <limits> 헤더에 정의된 std::numeric_limits를 사용하면 해당 타입이 표현할 수 있는 최
데이터 은닉과 접근 제어란?데이터 은닉(Data Hiding)은 객체 지향 프로그래밍(OOP)의 핵심 기능 중 하나입니다. 이를 통해 프로그램의 외부 함수가 클래스 타입의 내부 표현에 직접 접근하는 것을 막을 수 있습니다.클래스 멤버에 대한 접근 제한은 클래스 본문 내에서 라벨 형태의 접근 제한자(access modifier), 즉 public, private, protected 섹션을 사용해 지정합니다.특히 주의할 점은 클래스 내 멤버와 클래스 자체의 기본 접근 수준은 private이라는 것입니다. 접근 제한자를 명시하지 않으면