C 언어에서 전역 변수(global variable)와 정적 변수(static variable)는 반드시 상수 값으로 초기화해야 합니다. 그 이유는 프로그램 실행이 시작되기 전에 이 변수들의 값이 이미 결정되어 있어야 하기 때문입니다. 만약 전역 변수나 정적 변수를 상수가 아닌 값으로 초기화하려고 하면 컴파일 오류가 발생합니다.전역 변수와 정적 변수의 올바른 초기화 방법을 보여주는 예제 프로그램은 다음과 같습니다.예제 코드#include <stdio.h>int a = 5;static int b = 10;int main()
C 언어에서는 const 키워드 또는 #define 전처리기 지시문을 사용하여 변수를 상수로 선언할 수 있습니다. 두 가지 방법 모두 프로그램 실행 중 값이 변경되지 않아야 하는 데이터를 안전하게 관리하는 데 유용합니다. 각각의 사용법과 특징을 자세히 살펴보겠습니다.1. const 키워드변수의 자료형 앞에 const 키워드를 붙이면 해당 변수를 상수로 선언할 수 있습니다. 상수 변수는 선언 시 단 한 번만 초기화할 수 있으며, 이후에는 값을 변경할 수 없습니다. 만약 초기화하지 않고 선언하면 기본값은 0으로 설정됩니다.다음 예제는
C/C++에서 변수 이름은 영문 알파벳, 숫자, 밑줄(_) 문자로 구성할 수 있습니다. 언어에 내장된 키워드를 제외한 나머지 이름은 모두 식별자(identifier)로 취급되며, 식별자란 변수, 상수, 함수 등에 붙이는 이름을 의미합니다. 그런데 식별자는 반드시 숫자가 아닌 문자, 즉 알파벳이나 밑줄로 시작해야 합니다. 그 이유는 컴파일러가 소스 코드를 처리할 때 다음과 같은 일곱 단계를 거치기 때문입니다. 어휘 분석(Lexical Analysis) 구문 분석(Syntax Analysis) 의미 분석(Semantic Analysi
정수 승격이란 무엇인가?C 언어에는 int보다 적은 바이트를 차지하는 데이터 타입들이 있습니다. 대표적으로 char, short 등이 여기에 해당합니다. 흥미로운 점은, 이러한 작은 타입의 변수들에 연산을 수행하면 컴파일러가 자동으로 해당 값을 int 타입으로 변환한다는 것입니다. 이 과정을 정수 승격(Integer Promotion)이라고 부릅니다.정수 승격이 존재하는 이유는 대부분의 CPU가 int 크기(일반적으로 4바이트)의 연산을 가장 효율적으로 처리하기 때문입니다. 따라서 C 표준에서는 산술 연산 전에 작은 정수 타입을 i
정적 변수(static variable)는 static 키워드를 사용하여 정의할 수 있습니다. 정적 변수는 프로그램이 실행되는 동안 메모리에 계속 유지되는 변수로, 수명(lifetime)이 프로그램의 전체 실행 기간과 같습니다.이는 자동 변수(automatic variable)와 대비되는 특징입니다. 자동 변수는 해당 함수가 실행 중일 때만 메모리에 존재하며, 함수가 종료되면 소멸합니다.함수 수준 정적 변수의 초기화 시점함수 내부에 선언된 정적 변수는 처음 사용되는 시점에 생성 및 초기화됩니다. 다만 변수를 위한 메모리 공간 자체는
C 프로그래밍을 배우다 보면 포인터(pointer)와 배열(array)은 반드시 이해해야 하는 핵심 개념입니다. 두 개념은 메모리와 밀접한 관련이 있지만, 그 역할과 동작 방식에는 분명한 차이가 있습니다. 이 글에서는 포인터와 배열의 정의, 선언 방법, 예제 코드를 통해 두 개념의 차이점을 명확하게 살펴보겠습니다.포인터(Pointer)란?포인터는 다른 변수의 메모리 주소를 저장하는 변수입니다. 어떤 변수에 메모리가 할당되면, 포인터는 그 변수가 위치한 메모리 주소를 가리키게 됩니다. 포인터 변수를 선언할 때는 단항 연산자인 별표(*
C언어에서 2차원 배열 동적 할당이란? C언어에서는 단일 포인터를 사용하여 2차원 배열을 동적으로 할당할 수 있습니다. 이 방식은 malloc 함수를 통해 행 × 열 × 데이터 타입 크기만큼의 메모리 블록을 한 번에 할당하고, 포인터 산술 연산(pointer arithmetic)을 활용해 각 행렬 요소에 접근하는 방법입니다. 이 방법은 메모리가 연속적으로 할당되기 때문에 캐시 효율성이 좋고, 해제할 때도 free를 한 번만 호출하면 된다는 장점이 있습니다. 예제 코드 다음 프로그램은 2×3 크기의 2차원 배열을 동적으로 할당하고,
C 언어에서 2차원 배열은 함수의 매개변수로 손쉽게 전달할 수 있습니다. 다만 배열을 전달할 때는 컴파일러가 메모리 주소를 정확하게 계산할 수 있도록 열(column)의 크기를 반드시 명시해야 한다는 점에 유의해야 합니다.아래 예제는 행(row)과 열(column)의 크기가 모두 전역 상수로 선언되어 있을 때, 2차원 배열을 함수에 전달하여 각 요소의 값을 수정하는 방법을 보여줍니다.예제#include <stdio.h> const int R = 4; const int C = 3; void func(int a[R][C])
void 타입 배열이 허용되지 않는 이유C 언어에서는 int, char, float, double 등 대부분의 데이터 타입을 사용해 배열을 만들 수 있습니다. 하지만 void 데이터 타입으로는 배열을 생성할 수 없으며, 시도할 경우 컴파일 오류가 발생합니다.그 이유는 void가 크기가 정해지지 않은 불완전한(incomplete) 타입이기 때문입니다. 배열을 선언하려면 각 요소에 할당될 메모리 크기를 컴파일러가 알아야 하는데, void 타입은 요소 하나의 크기를 결정할 수 없어 배열 선언 자체가 불가능합니다.예제 코드다음 프로그램은
C 언어에서는 두 개의 큰따옴표( )를 사용하여 문자열 중간 어느 지점에서든 끊으면, 긴 문자열도 여러 줄에 걸쳐 작성할 수 있습니다. 컴파일러는 인접한 문자열 리터럴들을 자동으로 하나의 문자열로 연결해 주기 때문입니다.이를 보여주는 C 프로그램 예제는 다음과 같습니다.예제#include <stdio.h>int main() { char *str = This is the method &n
Java와 같은 언어에서는 배열을 선언된 범위를 벗어나 접근할 경우 java.lang.ArrayIndexOutOfBoundsException과 같은 예외가 발생하여 오류를 즉시 알려줍니다. 그러나 C언어에는 이러한 안전장치가 없기 때문에, 배열을 범위 밖으로 접근하더라도 컴파일러가 이를 잡아주지 못하고 정의되지 않은 동작(undefined behavior)이 발생할 수 있습니다.이는 프로그램이 비정상적으로 종료되거나, 엉뚱한 값이 출력되며, 심각한 경우 보안 취약점으로까지 이어질 수 있는 위험한 상황입니다. 아래의 C 프로그램 예제
strncpy() 함수는 원본(source) 문자열에서 지정된 개수만큼의 문자를 대상(destination) 배열로 복사하는 데 사용됩니다. 이름만 보면 strcpy()보다 더 안전해 보이지만, 실제로는 주의하지 않으면 심각한 문제를 일으킬 수 있는 함수입니다. strncpy()의 기본 구문 char *strncpy( char *destination, char *source, size_t n); 각 매개변수의 의미는 다음과 같습니다. destination: 원본 문자열이 복사되어 저장될 대상 배열을 가리키는 포인터 source:
C/C++에서 배열 인덱스가 0부터 시작하는 이유C/C++에서 배열의 인덱스가 왜 1이 아닌 0부터 시작하는지 궁금해한 적이 있을 것입니다. 그 답은 포인터 연산(pointer arithmetic)의 내부 동작 방식에 있습니다.핵심 원리: arr[i]는 *(arr + i)와 같다C/C++ 컴파일러는 배열 표기법 arr[i]를 항상 *(arr + i)로 해석합니다. 여기서 각 구성 요소의 의미는 다음과 같습니다.arr은 배열의 첫 번째 요소, 즉 인덱스 0번 요소가 저장된 메모리 주소를 나타냅니다. 따라서 *(arr + i)는 배열의
이 글에서는 <, <=, !=, >, >=, == 같은 비교 연산자를 비롯해 if 문과 같은 조건문을 하나도 사용하지 않고, 입력된 숫자가 홀수인지 짝수인지 판별하는 C 프로그램을 작성하는 방법을 소개합니다. 조건문을 자유롭게 쓸 수 있다면 문제는 아주 간단합니다. 숫자를 2로 나눈 나머지가 0이면 짝수, 그렇지 않으면 홀수로 판정하면 됩니다. 또는 숫자와 1을 비트 AND(&) 연산했을 때 결과가 0이면 짝수, 1이면 홀수라고 구분할 수도 있습니다. 하지만 이번에는 어떤 형태의 조건문도 사용할 수 없
이 글에서는 for, while 같은 반복문을 전혀 사용하지 않고 1부터 100까지의 숫자를 출력하는 C 프로그램을 작성하는 방법을 알아보겠습니다.재귀(Recursion)를 활용한 해결 방법이 문제는 재귀 함수(recursive function)를 이용하면 반복문 없이도 손쉽게 해결할 수 있습니다. 재귀 함수는 기본적으로 두 가지 요소로 구성됩니다.기저 사례(Base Case): 재귀 호출을 멈추는 조건재귀 호출(Recursive Call) 및 기타 연산: 자기 자신을 다시 호출하는 부분이번 예제에서 기저 사례는 인자 n이 1보다
이번 글에서는 세미콜론(;)을 하나도 사용하지 않고 Hello World라는 텍스트를 출력하는 C 프로그램을 작성하는 방법을 알아보겠습니다.일반적으로는 main() 함수 안에 다음과 같이 한 줄만 작성하면 됩니다.printf(Hello World);하지만 이 코드 끝에는 반드시 세미콜론이 붙습니다. 세미콜론을 사용하지 않으려면 약간의 트릭이 필요합니다.핵심 아이디어: if 조건문 활용하기비결은 printf() 함수를 if 조건식 안에 넣는 것입니다.C 언어에서 printf() 함수는 성공적으로 출력한 문자 수를 반환값으로 돌려줍니다
이번 글에서는 Ctrl + C 키를 눌러도 종료되지 않는 C 프로그램을 작성하는 방법을 알아보겠습니다.일반적으로 Ctrl + C 키는 키보드 인터럽트(keyboard interrupt)를 발생시켜 현재 실행 중인 프로세스를 중단시킵니다. 하지만 시그널(signal) 처리 기법을 활용하면 Ctrl + C가 눌렸을 때 프로세스를 종료하는 대신 특정 메시지를 출력한 뒤 계속 실행하도록 만들 수 있습니다.Ctrl + C가 눌리면 운영체제는 SIGINT라는 시그널을 프로그램에 전달합니다. C 언어에서는 이러한 시그널을 직접 처리(catch)
이 글에서는 서식 지정자(format specifier)를 일절 사용하지 않고 문자를 출력하는 방법을 살펴보겠습니다. C 언어의 서식 지정자에는 %d, %f, %c 등이 있으며, 보통 printf() 함수와 함께 사용되어 문자나 숫자를 화면에 출력합니다.그렇다면 %c 없이도 문자를 출력할 수 있을까요? 답은 가능입니다. 핵심 아이디어는 문자의 ASCII 값을 16진수 형태로 문자열 안에 직접 삽입하는 것입니다. C 언어에서는 문자열 리터럴 내에서 \x 뒤에 16진수 값을 붙이면 해당 ASCII 코드에 대응하는 문자로 해석되기 때문입
C 언어로 IP 주소 유효성 검사하기이 글에서는 C 언어를 사용해 IP 주소(IPv4)의 유효성을 검사하는 방법을 알아보겠습니다. IPv4 주소는 점-십진법(dot-decimal notation)으로 표현되며, 0부터 255 범위의 네 개의 십진수가 세 개의 점(.)으로 구분된 형태입니다.유효한 IP 주소의 예는 다음과 같습니다.192.168.4.1IP 주소 검증 절차주어진 IP 주소가 유효한지 판별하려면 다음 단계를 순서대로 수행해야 합니다.점(.) 구분자를 기준으로 IP 주소 문자열을 토큰 단위로 분리합니다.분리된 각 부분 문자
PGM(Portable Gray Map)이란?PGM은 Portable Gray Map, 즉 휴대용 그레이스케일 이미지 형식을 의미합니다. C 언어에서 2차원 배열 데이터를 PNG나 JPEG처럼 일반적인 이미지 형식으로 저장하려면, 파일에 기록하기 전에 지정된 형식에 맞게 데이터를 인코딩하는 복잡한 작업이 필요합니다.반면 Netpbm 포맷은 간단하면서도 이식성이 뛰어난 해결책을 제공합니다. Netpbm은 오픈 소스 그래픽 프로그램 패키지로, 주로 Linux나 Unix 환경에서 사용되며 Microsoft Windows 시스템에서도 문제