구조체와 공용체
·
Language/C
배열이 같은 자료형을 모은 것이라면, 구조체는 서로 다른 자료형을 하나로 묶어 새로운 형식을 만드는 문법이다. 이번 글에서는 구조체의 선언과 사용, 동적 할당, 함수와의 관계, 구조체를 멤버로 갖는 구조체와 연결 리스트, 그리고 비트필드·공용체·멤버 맞춤까지 다룬다.구조체 선언과 정의구조체는 여러 자료형을 모아 하나의 새로운 형식으로 기술하는 사용자 정의 형식이다. 배열이 같은 것들의 모임이고 인덱스로 접근한다면, 구조체는 서로 다른 것들의 모임이고 인덱스 대신 이름(멤버)으로 접근한다.#include #include struct USERDATA{ int nAge; char szName[32]; char szPhone[32];};int main(void){ struct USERDAT..
함수 응용 (2) — atoi, time, rand, system
·
Language/C
이번에는 표준 라이브러리가 제공하는 유틸리티 함수들을 정리한다. 문자열을 숫자로 바꾸는 변환 함수, 시간을 다루는 함수, 난수, 그리고 외부 명령 실행과 프로그램 종료 함수다. 각각 짧지만 자주 쓰이고, 알고 쓰지 않으면 함정에 빠지기 쉬운 것들이다.문자열을 숫자로 — atoi, atof문자열로 들어온 숫자를 실제 숫자 타입으로 바꿀 때 변환 함수를 쓴다. atoi는 정수로, atol은 long으로, atof는 실수로 변환한다.#include #include int main(void){ char szBuffer[32]; int nResult = 0; printf("Input string: "); gets_s(szBuffer, sizeof(szBuffer)); nResult = ..
함수 응용 (1) — call by reference와 Stack frame
·
Language/C
앞의 포인터 시리즈에서 메모리 구조와 주소, 동적 할당을 다뤘다. 이번에는 그 개념들을 함수에 적용한다. 함수에 값을 어떻게 넘기는지(call by value/reference), 지역변수의 수명과 Stack frame, 재귀 호출, 그리고 문자열 처리 함수와 버퍼 오버런까지 정리한다.매개변수 전달의 기본함수를 부르는 쪽을 Caller, 불리는 쪽을 Callee라고 한다. Caller가 Callee를 호출할 때 매개변수에 넘길 구체적인 값(실인수)을 적어주고, Callee가 값을 반환할 때까지 기다린다. Callee 입장에서 매개변수는 함수 안에서 지역변수처럼 쓰인다.매개변수가 어디에 담겨 전달되는지는 환경에 따라 다르다. 32bit에서는 Stack 메모리를 거쳐 전달되지만, 64bit에서는 CPU의 레..
메모리와 포인터 (3) — 문자열, 다차원 포인터, 정적 메모리
·
Language/C
앞의 두 편(1편, 2편)에서 메모리 구조, 포인터와 배열, 동적 할당까지 다뤘다. 이번에는 문자열을 다루는 표준 함수들, 할당된 메모리의 크기를 바꾸는 realloc(), 포인터를 여러 단계로 겹치는 다중 포인터, 다차원 배열을 가리키는 포인터, 그리고 함수가 끝나도 사라지지 않는 정적 메모리와 기억부류 지정자를 정리한다.문자열 복사 — strcpy_s문자열을 다른 곳으로 옮길 때 단순 대입을 쓰면 의도와 다른 일이 벌어진다.#include #include #include int main(void){ char szBuffer[] = "Hello"; char* pszBuffer = szBuffer; char* pszHeap = malloc(16); strcpy_s(pszHeap, 1..
메모리와 포인터 (2) — 포인터와 배열, 동적 할당
·
Language/C
앞 글에서 포인터가 주소를 담는 변수라는 것을 봤다. 이 글에서는 그 포인터로 배열을 다루는 법, 그리고 실행 중에 메모리를 직접 할당받아 쓰는 동적 할당을 본다.포인터와 1차원 배열배열 이름은 0번 요소의 주소다(배열 글에서 본 내용이다). 그래서 배열을 다룰 때는 그 요소의 형식을 가리키는 포인터를 선언해 쓰는 것이 일반적이다. int 배열은 int*로, char 배열은 char*로 관리한다.#include int main(void){ int aList[5] = { 0 }; int* pnData = aList; // 배열 이름 = 0번 요소 주소 // int* pnData = &aList[0]; // 위와 같은 의미 printf("aList[0] : %d\n", aL..
메모리와 포인터 (1) — 메모리 구조와 포인터 기초
·
Language/C
변수를 쓸 때마다 우리는 사실 메모리의 어떤 칸을 빌려 쓰고 있었다. 포인터를 이해하려면 먼저 그 메모리가 어떻게 생겼는지, 변수와 주소가 어떤 관계인지부터 봐야 한다.컴퓨터와 메모리CPU는 연산할 코드(기계어)와 그 대상이 되는 데이터를 모두 메모리에서 가져온다. 우리가 지금까지 변수를 통해 다뤄 온 것이 바로 이 메모리다. 메모리의 모든 칸은 고유한 주소를 가진다. 주소는 위치 정보이고, 단위는 바이트다. 64비트 시스템에서 메모리 주소의 길이는 64비트(8바이트)다.메모리는 아주 큰 표메모리를 엑셀 시트 같은 거대한 표로 생각하면 편하다. 각 셀(A1, A2…)이 메모리 한 칸이고, 셀 이름이 곧 주소다. 어떤 값을 읽거나 쓰려면 "몇 번 셀"인지 주소로 가리키면 된다.메모리 종류범용 OS(Wind..
C언어 함수
·
Language/C
지금까지는 거의 모든 코드를 main() 한곳에 몰아넣었다. 함수는 절차적 흐름을 가진 여러 구문을 하나로 묶어 이름을 붙이고, 호출을 통해 서로 연결하는 단위 코드다.함수란함수는 여러 구문을 하나로 묶은 단위 코드이자, C 프로그램을 구성하는 기본 단위다. C 프로그램은 함수들의 모임이고, 그중 main() 함수의 시작과 끝이 곧 프로그램의 시작과 끝이다. main()은 프로젝트에 반드시 하나 있어야 하며, 프로그램이 시작될 때 자동으로 호출된다. 함수는 다음 형식으로 기술한다.반환자료형 이름(매개변수 목록){ // 함수 바디}두 수를 더해 돌려주는 함수를 보자.#include int Add(int a, int b){ int nData = 0; nData = a + b; retur..
C언어 배열
·
Language/C
변수 하나에 값 하나를 담는 방식으로는 같은 종류의 데이터 수십 개를 다루기 어렵다. 배열은 같은 형식의 자료를 메모리에 연속으로 늘어놓고 번호로 꺼내 쓰는 자료 묶음이다.배열이란배열은 같은 자료형의 값 여러 개를 하나의 이름으로 묶고, 각 값을 인덱스(번호)로 구분하는 자료 구조다. 선언은 자료형, 이름, 대괄호 안의 개수로 한다.int aList[5];이렇게 선언하면 int 5개가 메모리에 연속으로 잡힌다. 각 요소는 aList[0], aList[1], … aList[4]로 접근한다. 인덱스는 0부터 시작한다(zero-based). 개수가 5면 유효한 인덱스는 0~4이고, aList[5]는 배열 밖이다.배열 범위C는 인덱스 범위를 검사하지 않는다. aList[5]나 aList[-1]에 접근해도 컴파일..
C언어 반복문
·
Language/C
반복문은 같은 코드를 조건이 만족되는 동안 되풀이하는 제어문이다. if가 흐름을 한 번 가른다면, 반복문은 조건을 반복해서 검사하며 같은 구간을 여러 번 실행한다. whilewhile은 if와 구조가 닮았다. 차이는 조건식이 참인 동안 구간 코드를 한 번이 아니라 계속 반복해서 수행한다는 점이다.while (조건식){ // 조건이 참인 동안 반복}반복 수행 구간 안에는 반복을 멈출 수 있는 연산이 반드시 있어야 한다. 조건을 언젠가 거짓으로 만드는 코드가 없으면 반복이 끝나지 않는다.무한루프는 최악의 논리 오류 중 하나조건이 영원히 참이면 프로그램이 멈추지 않는다. while을 쓸 때는 반복마다 조건에 영향을 주는 값이 변하는지, 그래서 언젠가 조건이 거짓이 되는지 반드시 확인한다. 카운터를 증가시..