C언어에서 배열 매개변수가 포인터로 취급되는 이유C언어가 배열 매개변수를 포인터로 취급하는 가장 큰 이유는 실행 속도와 효율성입니다. 함수 호출 시 배열의 모든 요소를 하나씩 복사해서 전달하는 방법도 있지만, 이 방식은 배열의 크기가 클수록 시간과 메모리가 많이 소모되어 매우 비효율적입니다.그래서 C언어는 배열의 첫 번째 요소 주소, 즉 기본 주소(base address)만 함수에 전달하는 방식을 사용합니다. 함수 내부에서는 이 포인터를 통해 배열의 나머지 요소들에 순차적으로 접근할 수 있습니다. 따라서 아래 두 함수 선언은 사실상
C/C++에서 배열 요소에 접근하는 가장 일반적인 방법은 array[i]와 같은 인덱스 표기법입니다. 하지만 배열 이름 자체가 첫 번째 요소를 가리키는 포인터로 해석된다는 점을 이용하면, *(array + i)와 같은 포인터 연산 방식으로도 동일한 결과를 얻을 수 있습니다. 아래는 이러한 흔하지 않은 표현 방식을 보여주는 간단한 C++ 프로그램입니다.예제 코드#include<iostream> using namespace std; int main() { int array[5] = {7,7,7, 6, 6}; for
C 언어에서 포인터(pointer)와 배열(array)은 대부분의 경우 서로 같은 것으로 취급됩니다. 실제로 배열 이름은 첫 번째 요소를 가리키는 주소처럼 동작하기 때문입니다. 하지만 두 개념 사이에는 중요한 차이점이 몇 가지 존재합니다.1. &(주소) 연산자의 차이&pointer : 포인터 변수 자체가 저장된 메모리 주소를 반환합니다.&array : 배열의 첫 번째 요소의 주소를 반환합니다.2. sizeof 연산자의 차이sizeof(array) : 배열의 모든 요소가 차지하는 전체 메모리 크기를 반환합니다.
C/C++에서 배열의 인덱스가 0부터 시작하는 데에는 명확한 기술적 이유가 있습니다. 핵심은 포인터 산술(pointer arithmetic)에 있습니다.포인터 연산 관점에서 본 배열 인덱싱배열의 이름은 사실상 배열의 첫 번째 요소를 가리키는 포인터처럼 동작합니다. 따라서 배열 인덱스가 0부터 시작하면 다음과 같이 간단하게 구현할 수 있습니다.a[i] → *(a + i)여기서 a는 배열의 첫 번째 요소(인덱스 0)의 메모리 주소를 나타내며, 여기에 i를 더하면 정확히 i번째 요소의 주소가 됩니다. 즉, 오프셋 계산이 한 번의 덧셈으로
4차원(4D) 배열이란 3차원 배열들을 다시 하나로 묶어놓은 배열을 의미합니다. 즉, 2×2×3×2 형태의 배열은 총 24개의 정수를 저장할 수 있는 공간을 가지며, 네 개의 인덱스를 사용하여 각 요소에 접근합니다.일반적으로 4차원 배열은 이미지 처리(색상·프레임), 과학 시뮬레이션, 텐서 연산 등 복잡한 데이터 구조가 필요한 분야에서 활용됩니다.알고리즘4차원 배열을 다루는 기본적인 절차는 다음과 같습니다.시작. 변수를 선언한다. 배열 요소를 선언한다. 저장할 요소의 개수를 입력받는다. 각 요소의 값을 입력받는
이 프로그램에서는 포인터 산술(pointer arithmetic)을 활용하여 배열 요소들의 합을 계산하는 방법을 알아봅니다.포인터의 기본 개념여기서 사용하는 연산자 *는 해당 메모리 주소에 저장되어 있는 값을 의미하며, 그 주소 자체는 변수에 저장됩니다. 따라서 int *ptr이라고 선언하면, ptr은 하나의 주소값을 담고 있는 변수이며, 그 주소에 저장된 내용은 정수형(integer) 값이라는 뜻입니다.즉, *p는 p가 포인터 변수임을 나타냅니다. 이 포인터 변수와 함수 s()를 함께 사용하면 배열의 모든 요소를 순회하면서 합계를
기존에 작성된 C 또는 C++ 기능을 Python에서 사용하도록 래핑하는 방법은 여러 가지가 있습니다. 이 글에서는 그중 SWIG(Simple Wrapper Interface Generator)를 이용해 C/C++ 기능을 Python으로 래핑하는 방법을 살펴보겠습니다.C/C++을 Python으로 래핑하는 대표적인 방법수동 래핑(Manual wrapping)Pyrex를 이용한 C 코드 래핑CtypesSIPBoost PythonSWIG는 C 코드를 Perl, Python, PHP, Ruby, Tcl, C#, Common Lisp(CLI
이번 글에서는 C 언어에서 문자열을 토큰(token) 단위로 분리하는 방법을 알아보겠습니다. C 표준 라이브러리는 이를 위해 strtok() 함수를 제공하며, 이 함수는 구분자(delimiter)를 기준으로 하나의 문자열을 여러 개의 토큰으로 나누는 역할을 합니다. strtok() 함수란? char *strtok(char *str, const char *delim) 함수는 문자열 str을 지정된 구분자 delim을 기준으로 일련의 토큰들로 분해합니다. 함수 선언 char *strtok(char *str, const char *d
C/C++에서 현재 작업 디렉터리 구하기이 글에서는 C 또는 C++ 프로그램에서 현재 작업 디렉터리(Current Working Directory), 즉 프로그램이 실행되고 있는 디렉터리의 전체 경로를 얻는 방법을 살펴보겠습니다.현재 작업 디렉터리를 가져오는 함수는 운영체제마다 다릅니다. Windows 계열에서는 <direct.h> 헤더에 정의된 _getcwd() 함수를 사용하고, Linux나 macOS 같은 UNIX 계열 시스템에서는 <unistd.h> 헤더에 정의된 getcwd() 함수를 사용합니다.따라서
C와 C++은 문법이 비슷해 보이지만, 문자 리터럴을 처리하는 방식에는 중요한 차이가 있습니다. C++에서 문자 리터럴(예: a)의 자료형은 char입니다. 반면 C 언어에서 문자 리터럴의 자료형은 정수형(int)으로 취급됩니다. 그렇기 때문에 C에서는 32비트 아키텍처 기준으로 sizeof(a)가 4를 반환하며, 한 바이트당 비트 수를 나타내는 CHAR_BIT 값은 8입니다. 반면 sizeof(char)는 C와 C++ 모두에서 항상 1바이트라는 점이 흥미롭습니다. C 예제 코드 #include<stdio.h> int
C/C++ 포인터의 일반적인 사용 수준실제 C 프로그램에서 자주 사용되는 포인터의 정적(static) 수준은 한두 단계가 일반적입니다. 예를 들어 int *p(단일 포인터)나 int **pp(이중 포인터) 정도가 대표적이며, 삼중 간접 참조(triple indirection)는 실무에서 드물게 등장합니다.하지만 흥미롭게도 무한한 수준의 포인터 간접 참조는 매우 흔하게 볼 수 있습니다. 그 핵심 열쇠는 바로 구조체(struct)입니다.구조체를 활용한 무한 간접 참조자기 자신과 같은 타입의 포인터를 멤버로 가지는 구조체를 정의하면, 포
C 언어에서 포인터(pointer)는 메모리 주소를 저장하는 변수로, 프로그램이 데이터에 직접 접근할 수 있게 해주는 핵심 개념입니다. 특히 16비트 도스(DOS) 시절의 x86 아키텍처에서는 메모리를 세그먼트(segment) 단위로 나누어 관리했기 때문에, 포인터의 종류에 따라 접근할 수 있는 메모리 범위가 달라졌습니다. 이때 사용된 것이 바로 근거리(Near), 원거리(Far), 거대(Huge) 포인터입니다.1. 근거리 포인터(Near Pointer)근거리 포인터는 16비트 크기의 주소만 저장하는 포인터입니다. 하나의 세그먼트(
C 프로그램은 실행될 때 명령줄(command line)에서 값을 전달받을 수 있습니다. 이렇게 전달되는 값들을 명령줄 인수(command line arguments)라고 부르며, 프로그램 내부에 값을 하드코딩하는 대신 외부에서 프로그램의 동작을 제어하고 싶을 때 매우 유용하게 활용됩니다.명령줄 인수는 main() 함수의 매개변수를 통해 처리됩니다. argc는 전달된 인수의 개수를 나타내고, argv[]는 프로그램에 전달된 각 인수를 가리키는 포인터 배열입니다.기본 예제다음 예제는 명령줄에서 인수가 전달되었는지 확인하고, 그 결과에
이번 글에서는 C와 C++에서 사용되는 exit() 함수와 _Exit() 함수의 차이점을 자세히 알아보겠습니다. 두 함수 모두 프로세스를 종료하는 역할을 하지만, 동작 방식에는 중요한 차이가 있습니다.exit() 함수란?C 언어의 exit() 함수는 호출된 프로세스를 즉시 종료하며, exit() 함수 호출 이후에 작성된 나머지 코드는 실행되지 않습니다.중요한 점은 exit()가 프로그램을 종료하기 전에 여러 가지 정리(cleanup) 작업을 수행한다는 것입니다. 예를 들면 다음과 같습니다.- 열려 있는 입출력 버퍼의 플러시(flus
C 언어에서는 fopen(), fseek(), ftell() 함수를 조합하면 파일의 크기를 손쉽게 구할 수 있습니다. 이 글에서는 파일 크기를 계산하는 C 프로그램의 알고리즘과 예제 코드, 실행 결과까지 단계별로 살펴보겠습니다.알고리즘시작 함수 findfileSize() 읽기 전용 모드(r)로 파일 포인터 fp를 연다. 만약 fp가 NULL이라면 파일을 찾을 수 없습니다를 출력하고 -1을 반환한다. 그렇지 않으면 파일 크기를 계산한다. fseek()로 파일 포인터를 파일의 끝
포인터는 변수의 주소(address)를 저장하는 데 사용됩니다. 그렇다면 포인터 대 포인터(pointer to pointer), 즉 이중 포인터(double pointer)란 무엇일까요? 이중 포인터에서는 첫 번째 포인터가 두 번째 포인터의 주소를 저장하는 역할을 합니다. 이처럼 포인터가 또 다른 포인터를 가리키기 때문에 이중 포인터라고 부릅니다.알고리즘시작 정수형 변수 v를 선언한다. v = 76으로 초기화한다. 정수형 포인터 p1을 선언한다. 정수형 이중 포인터 p2를 선언한다. p1을 변수
C 언어에서 NULL 포인터란?NULL 포인터(null pointer)는 어떤 유효한 객체나 함수도 가리키지 않는 특별한 포인터입니다. C 언어에서 NULL은 stdio.h, stddef.h 같은 헤더 파일에 정의된 매크로로, 일반적으로 0 또는 ((void*)0)으로 표현됩니다. 초기화되지 않은 포인터에는 예측할 수 없는 쓰레기 값(garbage value)이 들어갈 수 있기 때문에, 유효한 주소를 저장하기 전까지는 반드시 NULL로 초기화하는 습관이 중요합니다.NULL 포인터의 주요 용도1. 포인터 변수 초기화포인터 변수에 아직
C 언어에서 void 포인터(void pointer)는 특정 데이터 타입과 연결되지 않은 포인터를 의미합니다. 메모리상의 데이터 위치, 즉 변수의 주소를 가리키며, 타입에 구애받지 않고 다양한 자료형을 담을 수 있어 범용 포인터(general purpose pointer)라고도 불립니다.대표적으로 C 표준 라이브러리의 malloc()과 calloc() 함수는 동적 메모리 할당 시 void * 형태의 제네릭 포인터를 반환합니다. 이 덕분에 호출자는 반환된 포인터를 원하는 자료형으로 캐스팅하여 사용할 수 있습니다.void 포인터의 제한
널 포인터(null pointer)란 유효한 메모리 위치를 전혀 가리키지 않는 포인터를 의미합니다. C와 C++에서는 이러한 널 포인터를 표현하기 위해 일반적으로 주소 값 0이 사용됩니다.널 포인터의 주요 용도포인터 초기화: 포인터 변수에 아직 유효한 메모리 주소가 할당되지 않았다면, 널 포인터로 초기화하는 것이 좋습니다. 이렇게 하면 쓰레기 값(garbage value)으로 인한 예측 불가능한 동작을 방지할 수 있습니다.함수 인자 전달: 함수에 유효한 메모리 주소를 넘기고 싶지 않은 경우, 널 포인터를 인자로 전달할 수 있습니다.
디렉토리에 포함된 파일 목록을 확인해야 하는 경우가 종종 있습니다. C와 C++에서는 dirent.h 헤더 파일에서 제공하는 POSIX 표준 함수들을 활용하면 손쉽게 구현할 수 있습니다. 이 글에서는 실제 동작하는 예제 코드와 함께 그 원리를 자세히 살펴보겠습니다.핵심 함수 소개디렉토리 탐색에는 크게 세 가지 함수가 사용됩니다.opendir(): 지정한 경로의 디렉토리를 열고, 이후 작업에 사용할 DIR 타입의 스트림 포인터를 반환합니다.readdir(): 열려 있는 디렉토리에서 항목(파일 또는 하위 디렉토리)을 하나씩 읽어 dir