여러 개의 스레드가 동시에 실행될 때 각 스레드가 정해진 순서대로 숫자를 출력하도록 만드는 방법을 알아보겠습니다. 이 기법은 멀티스레드 프로그래밍에서 스레드 동기화(Thread Synchronization)의 핵심 개념을 이해하는 데 큰 도움이 됩니다. 동작 원리 먼저 n개의 스레드를 생성한 후, 이들을 동기화합니다. 목표는 첫 번째 스레드가 1을 출력하고, 두 번째 스레드가 2를 출력하는 식으로 번갈아 가며 숫자를 찍는 것입니다. 핵심 아이디어는 다음과 같습니다. 스레드가 출력을 시도할 때 먼저 뮤텍스(Mutex)로 공유 자원을
이 글에서는 멀티스레딩(Multi-threading) 개념을 적용하여 배열 안에서 특정 요소를 검색하는 방법을 알아봅니다. 접근 방식은 매우 간단합니다. 여러 개의 스레드를 생성한 뒤, 배열을 여러 구간으로 나누고 각 스레드가 서로 다른 구간을 담당하도록 합니다. 이후 검색 대상인 키(key) 값을 찾으면 플래그(flag) 변수를 설정하여 해당 요소의 존재 여부를 확인할 수 있습니다.동작 원리이 예제에서는 POSIX 스레드(pthread) 라이브러리를 사용합니다. 전체 흐름은 다음과 같습니다.배열 크기는 MAX(16), 스레드 개수
C 프로그래밍에서 엄격한 앨리어싱(strict aliasing) 규칙은 왜 지켜야 할까요? 이를 이해하기 위해, 먼저 간단한 예제 코드를 살펴보고 그 출력 결과를 분석해 보겠습니다.예제 코드#include<stdio.h> int temp = 5; int* var = &temp; int my_function(double* var) { temp = 1; *var = 5.10; // 이 연산이 temp의 값을 변경하게 됩니다 return (temp); } main() { printf(%d,
이번 글에서는 재미있는 프로그래밍 문제 하나를 살펴보겠습니다. 바로 C 언어를 이용해 크리스마스 트리를 무작위로 화면에 출력하는 방법입니다. 프로그램을 실행하면 마치 크리스마스 트리 전구처럼 트리가 계속 반짝이며 깜빡이는 효과를 확인할 수 있습니다.크리스마스 트리 출력의 기본 원리크리스마스 트리를 출력하려면 크기가 서로 다른 피라미드(삼각형) 모양을 여러 개 만들어 아래로 차곡차곡 겹쳐 그리면 됩니다. 트리를 장식하는 잎사귀는 미리 정해둔 문자 목록(., *, +, o, O) 중에서 무작위로 하나를 골라 출력하는 방식으로 표현합니다
이번 글에서는 C 언어의 wprintf()와 wscanf() 함수에 대해 자세히 알아보겠습니다. 이 두 함수는 각각 printf()와 scanf()의 와이드 문자(wide character) 버전으로, 유니코드 등 멀티바이트 문자를 다룰 때 유용하게 사용됩니다. 두 함수 모두 wchar.h 헤더 파일에 선언되어 있습니다.wprintf() 함수란?wprintf() 함수는 와이드 문자열을 표준 출력(콘솔)에 출력하는 데 사용됩니다. 출력 형식을 지정하는 와이드 문자열에는 % 기호로 시작하는 다양한 서식 지정자(format specifi
C나 C++ 코드를 보다 보면 025, 063처럼 숫자 리터럴 앞에 0이 붙어 있는 경우를 종종 볼 수 있습니다. 이 0은 단순한 장식이 아니라, 해당 숫자가 8진수(octal)임을 나타내는 중요한 표기법입니다.8진수 표기법의 기본 규칙C/C++에서는 숫자 상수가 0으로 시작하면 컴파일러는 이를 10진수가 아닌 8진수로 해석합니다. 따라서 8진수 값 25를 코드에 사용하려면 반드시 025처럼 앞에 0을 붙여 작성해야 합니다.참고로, 16진수는 0x 또는 0X 접두사(예: 0x1A)를 사용하고, 2진수는 C++14부터 0b 접두사(예
C++ 함수 오버로딩과 컴파일러의 처리 방식C++는 함수 오버로딩(Function Overloading) 기능을 제공합니다. 이 기능을 활용하면 같은 이름을 가진 여러 개의 함수를 정의할 수 있으며, 각 함수는 매개변수의 타입이나 개수만 다르면 됩니다. 단, 반환 타입은 오버로딩 구분에 사용되지 않습니다.그렇다면 C++ 컴파일러는 오브젝트 코드(Object Code) 수준에서 이렇게 동일한 이름을 가진 오버로딩된 함수들을 어떻게 구분할까요?비밀은 바로 이름 맹글링(Name Mangling)이라는 기법에 있습니다. 컴파일러는 오브젝트
C 언어에서 파일을 다루는 것은 프로그램이 데이터를 영구적으로 저장하고 필요할 때 다시 불러올 수 있게 해주는 핵심 기능입니다. 이 글에서는 C에서 가장 많이 사용되는 기본적인 파일 처리 작업 세 가지를 예제 코드와 함께 단계별로 살펴보겠습니다.파일에 데이터 쓰기파일에서 데이터 읽기파일에 내용 추가(append)하기1. 파일에 쓰기파일에 내용을 쓰려면 fopen() 함수를 w(쓰기 모드)로 호출한 뒤, fprintf()로 데이터를 기록하고 fclose()로 파일을 닫으면 됩니다. 아래 예제를 통해 전체 흐름을 확인해 보세요.예제 코
C90 표준에서는 배열을 반드시 고정된 순서로 초기화해야 했습니다. 즉, 인덱스 0, 1, 2… 순서대로 값을 나열하는 방식이 유일했습니다. 그러나 C99 표준부터 지정 초기화(Designated Initialization) 기능이 도입되면서 원하는 순서대로 요소를 자유롭게 초기화할 수 있게 되었습니다. 초기화는 배열 인덱스 또는 구조체 멤버 이름을 사용해 수행할 수 있으며, 참고로 이 확장 기능은 GNU C++에서는 지원되지 않습니다. 배열 인덱스를 이용한 지정 초기화 특정 인덱스에 값을 지정하려면 다음과 같이 작성합니다. int
C/C++에서 변수가 NULL인지 확인하는 방법C나 C++에서는 NULL 값을 비교하기 위한 별도의 전용 메서드가 제공되지 않습니다. 대신 if 문을 사용하여 변수가 NULL인지 여부를 간단하게 확인할 수 있습니다.아래 예제에서는 시스템에 존재하지 않는 파일을 읽기 모드로 열어보겠습니다. 이 경우 fopen() 함수는 NULL을 반환하며, if 문으로 이를 검사하여 파일 열기 실패 여부를 판단할 수 있습니다.예제 코드#include <stdio.h>main() { // 존재하지 않
C와 C++에서는 컴파일러가 프로그램의 동작을 보장하지 않는 상황이 존재합니다. 이를 정의되지 않은 동작(Undefined Behavior, UB)이라고 부르며, 같은 코드라도 컴파일러나 실행 환경에 따라 전혀 다른 결과를 낳을 수 있습니다.이 글에서는 대표적인 정의되지 않은 동작 사례들을 코드 예제와 함께 살펴보고, 각각 어떤 런타임 오류나 예기치 않은 결과를 유발하는지 알아보겠습니다.1. 0으로 나누기정수를 0으로 나누는 연산은 표준에서 정의되지 않은 동작으로 규정되어 있습니다. 런타임 오류가 발생하거나 프로그램이 비정상 종료될
C, C++, Java에서는 부동 소수점(float) 수를 대상으로 다양한 수학 연산을 수행합니다. 이번 글에서는 부동 소수점 수가 결합 법칙(associativity rule)을 따르는지 직접 확인해 보겠습니다. 결론부터 말하면 아니요. 부동 소수점 수는 특정한 경우에 결합 법칙을 따르지 않습니다. 아래 예제 코드를 통해 그 이유를 살펴보겠습니다. 예제 코드 #include<iostream> using namespace std; main() { float x = -500000000;
C++에는 인라인 함수(inline function)라는 유용한 기능이 있습니다. 인라인 함수는 C나 C++의 매크로와 비슷한 역할을 하며, 사용하려면 inline 키워드를 명시해야 합니다. 이러한 함수는 어디에서든 활용할 수 있지만, 효과적인 사용을 위해 몇 가지 가이드라인을 따르는 것이 좋습니다. 인라인 함수를 사용하면 좋은 경우 매크로(#define)를 대체할 때 — 매크로 대신 인라인 함수를 사용하면 타입 검사가 가능하고 디버깅도 쉬워지는 등 여러 장점이 있습니다. 작은 함수일 때 — 코드 크기가 작은 함수를 인라인으로
C 언어에서 형식 지정자(Format Specifier)는 입력과 출력을 위해 사용되는 특수 기호입니다. 이 개념을 활용하면 컴파일러가 scanf() 함수로 입력을 받거나 printf() 함수로 출력할 때 변수에 담긴 데이터가 어떤 자료형인지 정확히 판단할 수 있습니다.주요 형식 지정자 목록형식 지정자자료형 / 용도%c문자(Character)%d부호 있는 정수(Signed integer)%e 또는 %E실수의 과학적 표기법%f실수(Float) 값%g 또는 %G%e, %E와 유사한 실수 표기%hi부호 있는 short 정수%hu부호 없는
C++ 언어는 C 언어에 객체 지향(Object Oriented) 개념과 같은 다양한 기능을 추가하여 설계된 언어입니다. 그래서 대부분의 C 프로그램은 C++ 컴파일러로도 문제없이 컴파일됩니다. 하지만 C에서는 허용되는 문법 중 일부가 C++에서는 허용되지 않기 때문에, 모든 C 프로그램이 C++ 컴파일러에서 컴파일되는 것은 아닙니다.이번 글에서는 C 컴파일러에서는 정상적으로 컴파일되지만 C++ 컴파일러에서는 오류가 발생하는 대표적인 사례들을 코드 예제와 함께 하나씩 살펴보겠습니다. 1. 함수를 선언하기 전에 호출하는 경우 C++에
C와 C++는 문법이 매우 비슷해 보이지만, 실제로는 미묘한 차이가 여러 곳에 존재합니다. 같은 소스 코드라도 C 컴파일러로 빌드했을 때와 C++ 컴파일러로 빌드했을 때 서로 다른 결과가 나오는 경우가 있습니다. 이번 글에서는 그런 대표적인 예시 몇 가지를 살펴보겠습니다.1. 문자 리터럴의 크기 차이C와 C++에서 문자 리터럴은 서로 다른 방식으로 처리됩니다. C에서는 문자 리터럴이 int 타입으로 취급되지만, C++에서는 char 타입으로 취급됩니다. 따라서 sizeof() 연산자로 크기를 확인하면 C에서는 4, C++에서는 1이
C 표준 라이브러리의 char *ctime(const time_t *timer) 함수는 인자로 전달된 타이머 값을 기반으로 현지 시간(local time)을 나타내는 문자열을 반환합니다.반환되는 문자열은 다음과 같은 형식을 따릅니다 — Www Mmm dd hh:mm:ss yyyy. 각 부분의 의미는 아래와 같습니다.Www : 요일 (예: Thu, Fri)Mmm : 월 이름 (예: May, Jun)dd : 일 (날짜)hh:mm:ss : 시:분:초yyyy : 연도함수 문법ctime() 함수의 기본 문법은 다음과 같습니다.char *ct
포인터 배열은 여러 개의 포인터를 하나의 배열로 관리할 수 있게 해주는 C/C++의 강력한 기능입니다. 이 글에서는 일반 배열부터 시작해 정수형 포인터 배열, 문자열을 저장하는 포인터 배열까지 단계별로 살펴보겠습니다.기본 배열 예제먼저 3개의 정수를 저장하는 일반적인 배열의 사용 예를 살펴보겠습니다.C 언어 예제#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i; for (i = 0; i < M
C 언어에서는 표준 라이브러리 헤더 파일뿐만 아니라 개발자가 직접 만든 사용자 정의 헤더 파일도 활용할 수 있습니다. 자주 사용하는 함수들을 별도의 헤더 파일로 분리해 두면 코드의 재사용성이 높아지고 관리가 한결 수월해집니다.헤더 파일 작성 절차함수 코드를 작성한 뒤 sub.h라는 이름으로 저장합니다.메인 프로그램 subtraction.c를 작성하면서 다음 사항을 지켜야 합니다.#include 문으로 새로 만든 헤더 파일을 포함시킵니다.<sub.h>가 아닌 sub.h 형태로 작성합니다. 사용자 정의 헤더 파일은 큰따옴표로
파일 존재 여부 확인의 기본 원리표준 C/C++에는 파일의 존재 여부를 직접 반환해 주는 전용 함수가 없습니다. 따라서 가장 확실하고 이식성 높은 방법은 해당 파일을 읽기 또는 쓰기 모드로 실제로 열어 보는 것입니다. 파일 열기에 성공하면 파일이 존재하는 것이며, 실패하면 파일이 없거나 접근 권한이 없는 경우입니다.다음은 C와 C++에서 이를 구현한 예시 코드입니다.C에서 파일 존재 여부 확인하기C에서는 <stdio.h> 헤더에 정의된 fopen() 함수를 사용해 파일을 열어 볼 수 있습니다. fopen()이 NULL이