Category (Click)
Project
etc
VarOfLa / 차완기
/
강의노트
/
개발보드 덕질하기
펌웨어
하드웨어
소프트웨어
개발툴
AiMate
GamePad Bridge
LEXON MOD
FFXIV
NAVER Blog
VarOfLa / 차완기
/
강의노트
/
Share
Category (Click)
개발보드 덕질하기
펌웨어
하드웨어
소프트웨어
개발툴
Project
AiMate
GamePad Bridge
LEXON MOD
etc
FFXIV
NAVER Blog
📚
강의노트
최근 10개 글 보기
[IoT 맛보기] HC-06 → 스마트폰 LED 원격제어
2024/08/27 22:45
[IoT 맛보기] HC-06 → 스마트폰 LED 원격제어
2024/08/27 22:45
Otto 조립 방법
2023/10/29 11:33
Otto 조립 방법
2023/10/29 11:33
[2023 방통대 C 스터디] 12. [malloc.h] 양날의 검, 동적 메모리 할당
2023/05/11 14:00
[2023 방통대 C 스터디] 12. [malloc.h] 양날의 검, 동적 메모리 할당
2023/05/11 14:00
[2023 방통대 C 스터디] 11. [memory.h] 데이터를 복사할 땐,
2023/05/11 13:59
[2023 방통대 C 스터디] 11. [memory.h] 데이터를 복사할 땐,
2023/05/11 13:59
[2023 방통대 C 스터디] 10. [string.h] 파이썬은 되던데…
2023/05/11 13:59
[2023 방통대 C 스터디] 10. [string.h] 파이썬은 되던데…
2023/05/11 13:59
[2023 방통대 C 스터디] 9. [함수 포인터] 함수도 사실..
2023/05/11 13:59
[2023 방통대 C 스터디] 9. [함수 포인터] 함수도 사실..
2023/05/11 13:59
[2023 방통대 C 스터디] 8. [참조에 의한 호출] 마법!!!!
2023/05/11 13:59
[2023 방통대 C 스터디] 8. [참조에 의한 호출] 마법!!!!
2023/05/11 13:59
[2023 방통대 C 스터디] 6. [배열 활용] 큰 수의 계산
2023/05/11 13:59
[2023 방통대 C 스터디] 6. [배열 활용] 큰 수의 계산
2023/05/11 13:59
[2023 방통대 C 스터디] 6. [배열] 문자열
2023/05/11 13:59
[2023 방통대 C 스터디] 6. [배열] 문자열
2023/05/11 13:59
[2023 방통대 C 스터디] 5. [포인터] 변수는 어디에 저장될까?
2023/05/11 13:59
[2023 방통대 C 스터디] 5. [포인터] 변수는 어디에 저장될까?
2023/05/11 13:59
Load more
모든 글 보기
[IoT 맛보기] HC-06 → 스마트폰 LED 원격제어
Otto 조립 방법
변수의 메모리 할당에는 할당 시점에 따라
정적 할당
과
동적 할당
두 가지 방법이 있습니다.
정적 할당은 위 코드와 같이 변수에 사용할 메모리의 공간을 미리 정해두는 것입니다. 이렇게 만들어진 변수들은 컴파일 과정에서 할당될 메모리의 크기가 연산되고 프로그램에 저장됩니다. 정적으로 할당된 변수들은 크기가 고정되기 때문에 공간이 부족한 경우 늘릴 방법이 없습니다.
이와 반면에 동적 할당은
malloc.h
의
동적 메모리 할당 함수
를 이용해 상황에 맞게 메모리의 공간을 조절할 수 있습니다. 지금 사용하고 있는 Notion뿐만 아니라 브라우저, 게임 등 대부분의 프로그램에서 필요한 메모리의 공간을 미리 알 수 없기 때문에 메모리를 동적으로 할당하는 기법을 사용합니다.
메모리 할당 -
malloc()
memory allocation
의 약자인
malloc()
함수는 지정한 크기의 메모리 블록을 할당하고, 해당 메모리 블록의 시작 주소를 반환합니다.
•
size
: 할당할 메모리 공간(byte단위)
•
반환값: 할당된 메모리 블록의 시작 주소. 할당 실패 시 NULL 반환
만약 int형 변수 하나를 위한 공간을 생성한다면 인자값으로
sizeof(int)
를 입력하고, 2칸의
int
형 배열을 입력한다면
sizeof(int) * 2
를 입력하면 됩니다. 이때 반환값은
void *
타입이기 때문에 타입 지정 포인터에 저장하기 위해서는 형 변환이 필요합니다.
코드
위 예제는 문자열
“Hello, World!”
가 저장된 배열
str_p
를 다른 메모리 공간에 복사한 후 복사된 배열의 포인터를
char
형 포인터 변수
str_cpy_p
에 저장하는 예제입니다.
[2023 방통대 C 스터디] 12. [malloc.h] 양날의 검, 동적 메모리 할당
이전까지 변수의 종류인 자료형에 대해 알아보았으니 이제는 이걸 사용할 차례입니다.
우선 변수는 아래와 같은 방식으로 선언(declaration)합니다.
앞선
의
자료형의 이름을 먼저 작성
하고
그 뒤에는 변수의 이름
을, 그 뒤에는
코드 한 줄 이 끝났음을 의미하는 세미클론(
;
)을
입력합니다.
이렇게 변수를 생성하게 되면 메모리에는 자료형의 크기 만큼의 공간이 생기고 그 공간이 변수의 이름인 foo와 연결되는데요, 처음 변수를 생성하면 그 공간 안에는 소위 “쓰레기 데이터”라 부르는 일정하지 않은 값이 들어있게 됩니다. 변수를 선언한 후 처음 값을 설정하는 행위를 init(initialization, 초기화) 과정이라 합니다.
쓰레기 데이터(garbage value)는 이전에 사용하던 프로그램에서 메모리를 사용하다가 반환한 공간의 데이터입니다. 새 프로그램에서 변수를 생성해 메모리를 할당받게 되면 그 위치가 이전 프로그램에서 할당한 위치와 반드시 동일하고 겹치는 것은 아니기 때문에 알 수 없는 데이터, 즉 쓰레기 데이터가 출력되는 것입니다. 만약 정말 우연으로 동일한 위치가 겹쳐버리면 유효한 데이터가 나오겠죠?
변수의 init을 위해서는 변수에 데이터를 저장하기 위해서는 변수의 이름과
대입 연산자
기호인
=
, 변수에 넣을 데이터(숫자)를 입력하고 마찬가지로 끝에는 세미클론을 입력합니다.
물론 변수를 선언하며 init 과정을 거칠수도 있습니다. 위와 같이 변수 선언 과정에서 대입 연산자를 사용하면 변수를 선언하며 동시에 init을 진행합니다.
앞서 배운 자료형을 모두 변수로 선언하면 아래와 같습니다.
변수의 저장
앞서
에서 언급한것과 같이 모든 프로그램은 컴퓨터 메모리에 저장됩니다. 메모리의 구조를 그림으로 그리자면 아래와 같이 그릴 수 있습니다.
[2023 방통대 C 스터디] 4. [변수] 박스 그 자체
[2023 방통대 C 스터디] 5. [구조체/공용체] 데이터 묶어주기
주소 연산자
&foo;
앞선
섹션에서 변수의 저장에 대해 자세히 알아보았는데요, 이렇게 저장되는 모든 변수는 자신이 위치한 메모리의 고유 주소를 가지고 있습니다.
위 코드와 같이 변수를 생성한 후 변수 앞에
&
기호를 붙여주면 변수의 주소값을 알아낼 수 있습니다. 여기서
&
기호는
주소연산자
라고 부르며,
printf()
함수에서 주소값을 출력하기 위해 형식 지정자로
%p
를 사용합니다. 메모리 주소는 16진수를 사용하기 때문에 출력된 결과를 확인해보면
0x…
으로 시작하는 16진수 값을 확인할 수 있습니다.
범용 포인터 변수
void *foo;
그렇다면 이제 이 포인터를 어딘가에 저장해보아야겠죠? 포인터를 저장히기 위해서는 포인터 변수를 생성해야 합니다. 그러기 위해서는 포인터를 저장할 수 있는 변수를 생성해야 하는데요, 변수의 타입은 void로, 변수 이름 앞에는 별표 또는 Asterisk라고 부르는
*
문자를 붙여주어야 합니다.
요즈음 출시되는 대부분의 컴퓨터는 64bit 운영체제를 사용합니다. 여기서 64bit라는 수치는 메모리의 주소가 64bit 변수로 표현된다는 뜻이며, 메모리를 최대한으로 구성했을 때 8bit짜리 메모리 블럭이 2의 64승만큼 존재한다는 뜻입니다. 따라서 포인터 역시 0부터 2의 64승까지의 데이터를 저장할 수 있어야 하는데요, 이때문에 64bit 운영체제에서의 모든 포인터는
64bit
(
8byte
)의 공간을 차지합니다.
말이 어려워서 포인터이지 변수의 주소값을 저장하는
unsigned long long
형 변수(
uint64_t
)라 생각하면 편합니다.
또한 포인터 역시 변수이기 때문에 포인터 변수의 주소값을 얻을 수도 있습니다.
이러한 포인터의 포인터를 변수에 저장하기 위해서는
*
를 2번 붙여 변수를 생성하면 됩니다.
포인터 변수
는 그렇다 쳐도
포인터 변수의 포인터
는 도대체 어디다가 쓰는지 궁금할 수도 있는데요, 뒤에서 설명할 포인터의 용도에 대해 알게 된다면 자연스럽게 이해가 될겁니다.
[2023 방통대 C 스터디] 5. [포인터] 변수는 어디에 저장될까?
정렬 아니고요, 변수 다발입니다.
배열
이라는 명칭은 다양한 의미를 가지고 있어 햇갈리기가 쉽습니다. C언어에서의
배열
은 동일한 자료형을 연속적으로 메모리에 저장하는 자료 구조입니다. 1, 2, 3, 4와 같이 숫자를 저장하면
수열
(숫자 배열)이, a, b, c, d와 같이 문자를 저장하면
문자열
(문자 배열)이 되는 것이죠. 아래 내용을 통해
문자열
에 대해 알아보도록 하겠습니다.
이미 여러분들은 하나의 문자를 표현하기 위해서는
char
형 변수를 사용하고, 이 변수에 ASCII 코드에 대응되는 숫자를 넣는다는 것을 알고 있을텐데요, 이를 코드로 표현하자면 위와 같습니다.
그런데,
a
가 아니라
abcd
를 변수로 저장하고 싶다면 어떻게 해야할까요?
chat
형이 1 byte이니 4 byte짜리 자료형(
int
)에다가 저장하는걸까요?
물론… 시프트 연산자를 활용하면 할 수는 있지만, 비트연산을 생각하자니 상당히 고통스럽고 귀찮습니다. 그런데, 만약 abcd보다 더 긴 것을 저장한다면 어떻게 될까요? 가장 큰 자료형인
long long
을 넘기면 이런 방식으로는 해결할 수가 없죠.
바로 이럴 때
배열(Array)
을 사용합니다. 위의 소스코드에서 6번 줄을 실행한 후에는 위 사진 중 왼쪽과 같이 메모리에 데이터가 저장되는데요, 이걸 약간 변형해 오른쪽 사진과 같이 저장되도록 하는것이
배열
입니다.
배열을 적용하면 이렇게 코드로 구현할 수 있습니다. 위의 코드를 이해하려 하지는 마시고, 아래 내용을 통해 배열에 대해 자세히 알아보도록 하겠습니다.
배열 선언
배열을 선언할 때에는 변수 선언과 마찬가지로
(자료형)
(변수 명)
순으로 작성하면 되는데요, 이때
변수 명
뒤에 대괄호(
[]
)를 쓰고 대괄호 속에 배열의 길이를 입력합니다. 이렇게 코드를 작성하면 char 자료형의 변수가 메모리 상에 연속적(일렬)으로 4개 생성됩니다.
[2023 방통대 C 스터디] 6. [배열] 문자열
[2023 방통대 C 스터디] 6. [배열 활용] 큰 수의 계산
포인터는 어디에 사용할까요? 포인터는 메모리를 직접 조작할 수 있는
마법과도 같은 강력한 수단
이기 때문에 아주 다양한 목적으로 활용할 수 있습니다. 포인터를 활용하는 몇 가지 예시를 소개해보도록 하겠습니다.
값에 의한 호출
위의 코드는 변수 a에 0을 저장하고
add()
함수에 변수 a를 넣어 1을 더하도록 의도한 코드입니다. 결과는 어떻게 될까요? 의도한 것과 다르게 0이 출력됩니다.
왜 그럴까요?
이는 함수
add()
가
값에 의한 호출
방식으로 실행되기 때문입니다.
add()
함수가 실행될 때 매개변수
add_a
에는 인자값
a
가 복사되어 버립니다. 즉,
a
와
add_a
는 다른 변수인 것이죠.
함수에 대한 햇갈리기 쉬운 용어가 다수 등장합니다.
실제로 함수 안과 밖에서 변수
a
와
add_a
의 메모리 주소값을 출력해보면 서로 다른 것을 알 수 있습니다.
add()
함수 안에서 아무리
add_a
매개변수를 수정해봤자 밖의 변수
a
와 메모리 주소가 다르기 때문에 바꾼 내용이 저장되지 않겠죠.
참조에 의한 호출
그럼 대신
add()
함수에 변수
a
의 메모리 주소번지를 인자값으로 넘기면 어떻게 될까요?
add()
함수의 인자값으로
a
변수의 주소(
&a
)를 넣기 위해 매개변수를 포인터형으로 수정하고(
int *add_a
), 역참조 연산자를 이용해 메모리 주소의 데이터에 1을 더하도록(2번 줄) 수정했습니다. 함수 속의
printf()
함수 역시 포인터를 출력하도록(3번 줄) 변경합니다.
이렇게 수정한 후 코드를 실행하면
add()
함수에서 변수
a
의 메모리를 직접 접근해 1을 더해버리게 됩니다. 결론적으로
add()
함수가 실행된 후에는
a
에 1이 더해지게 되겠죠.
[2023 방통대 C 스터디] 8. [참조에 의한 호출] 마법!!!!
[2023 방통대 C 스터디] 9. [함수 포인터] 함수도 사실..
[2023 방통대 C 스터디] 10. [string.h] 파이썬은 되던데…
앞서 알아본 string.h 라이브러리를 사용하면 문자열을 간편하게 복사할 수 있었습니다. 그럼 문자열 이외의 숫자 배열이나 구조체의 배열 등은 어떻게 복사할까요?
일반적인 자료형의 변수부터 배열, 주조체 등 모든 변수들은 메모리에 저장되기 때문에 메모리 속의 내용을 복사해버리면 간단하게 해결됩니다. memory.h 라이브러리 의 주요 함수를 알아보도록 하겠습니다.
데이터 복사 -
memcpy()
memcpy() 함수는 메모리를 복사하는 함수입니다.
•
dest
: 복사 대상 메모리 블록을 가리키는 포인터
•
src
: 복사할 메모리 블록을 가리키는 포인터
•
n
: 복사할 바이트 수
•
반환값 : 복사 성공 시
*dest
일반적으로 복사할 바이트의 수의 계산에는
sizeof()
연산자를 사용합니다. 예를 들어
char
타입의 4칸짜리 배열(또는 길이가 4인 문자열)의 크기는 아래와 같이 알아낼 수 있습니다.
배열의 복사
코드
위 코드는
member_t
형 구조체 배열인
members
를 동일한 구조체 배열인
members_cpy
에 복사하는 예제 코드입니다. 배열이건 구조체건 간에 메모리에 연속적으로 저장된 데이터이기 때문에 복사 할 데이터의 시작 지점(포인터)과 데이터의 크기만 알면 복사할 수 있습니다. 여기에서는
members
의 크기를 알아내기 위해 구조체의 크기를
sizeof()
연산자를 통해 알아낸 뒤 배열의 길이인 2를 곱해
memcpy()
함수의 세 번째 인자값으로 전달하였습니다.
[2023 방통대 C 스터디] 11. [memory.h] 데이터를 복사할 땐,
[2023 방통대 C 스터디] 2. Hello, World!
앞서 작성했던 간단한 프로그램은 단순히 출력을 하기 때문에 데이터를 어딘가에 저장할 필요가 없었습니다. 하지만 이후 배울 키보드 입력 함수를 이용하다 보면 데이터를 어디에 저장하고 사용해야 할 필요가 생기게 됩니다. 모든 프로그래밍 언어에서는 이를 위한 변수 기능을 제공하는데요, 이러한 변수 기능을 이용하면
컴퓨터의 메모리에 특정 크기의 공간을 마련해
자료를 저장할 수 있습니다.
프로그램은 실행되기 전에는 보조 기억장치(HDD, SSD)에 저장되어 있다가 실행하게 되면 함수와 변수가 메모리(RAM)에 적재됩니다.
여기서 변수가 저장되는 공간의 크기에 따라 들어갈 수 있는 데이터의 범위가 달라지게 되는데요, 이처럼 변수에 저장되는 데이터의 종류를
자료형
이라 합니다. C언어에서 사용되는 자료형의 종류는 크게 정수형, 실수형 두 종류가 있으며 같은 정수형이라 하더라도 표현할 수 있는 수의 범위(공간의 크기)에 따라 세분화된 여러 종류가 있습니다.
큰 수를 표현할 필요가 없는데 변수에 메모리를 많이 할당(=공간을 크게 설정=저장할 수 있는 수위 범위가 크게)하는 것은 낭비이겠죠? 따라서 변수를 사용하려는 목적에 알맞게 자료형을 선택하는것이 좋습니다.
정수형(Integer)
정수형은 소숫점이 없는 숫자를 의미합니다.
•
char
:
character
의 약자로, 주로 문자 하나를 저장하기 위해 사용,
1 byte (8 bit)
•
short
:
int
와
char
사이 크기의 변수.
2 byte (16 bit)
•
int
:
integer
의 약자로, 정수 형태의 자료형이 필요하다면 주로 사용
4 byte (32 bit)
•
long
:
int
보다
컸던
자료형으로, 64bit OS에서는
int
와 동일한
4 byte (32 bit)
공간을 가짐
•
long long
:
int
,
long
보다 큰 자료형으로,
8 byte (64 bit)
공간을 가짐
여기서
노란색
으로 표시한 부분은 각 자료형의 크기를 의미합니다. 자료형의 크기 만큼 메모리에 공간을 할당받게 되고 그 공간의 각 비트를 켜고 꺼(2진법) 숫자를 표현합니다. 예를 들어 1 byte의 크기를 가지는 char형은 1 byte = 1*8 bit이기 때문에 8개의 비트가 있으며, 이 8개의 비트를 2진법으로 켜고 끈다면 0~2^8-1 = 0~255까지 총 256 단계를 표현할 수 있습니다. 이것을 음수의 범위를 표현하기 위해 반으로 잘라 -128~127까지 표현하도록 하는 것입니다.
여기서 음수가 하나 더 많은 이유는 PC에서 음수의 표현을 위해 2의 보수법을 사용하여 0이 양수로 취급되기 때문입니다.
따라서 정수형의 표현 범위를 계산해 정리하면 아래와 같습니다.
[2023 방통대 C 스터디] 3. [자료형] C언어의 기본!
C?
C언어는 1972년에 벨 연구소의 데니스 리치와 켄 톰슨이 개발한 프로그래밍 언어입니다. 초기에는 유닉스 운영체제의 개발 목적으로 만들어졌으며, 이후에는 시스템 프로그래밍 언어로 널리 사용되었습니다.
C언어는 절차적 프로그래밍 언어로, 명령어들의 집합으로 구성되어 있습니다. 프로그래머는 변수, 함수, 구조체 등을 이용하여 프로그램을 작성하며, 이를 컴파일러를 통해 컴퓨터가 실행할 수 있는 기계어로 변환합니다. C언어는 이식성이 높고, 강력한 기능을 가지고 있어서, 다양한 분야에서 사용되고 있습니다.
여기서 절차적 프로그래밍 언어라는 것은 프로그래밍 언어가 순서적이라는 관점을 가졌다는 뜻입니다. 이러한 관점을
프로그래밍 패러다임
이라 부르는데요, 절차적 프로그래밍 언어인 C언어는 작성한 순서대로, 즉 A→B→C로 코드를 작성하면 반드시 A→B→C로 작동하는 성질을 가졌습니다.
C언어는 시스템 프로그래밍, 임베디드 시스템, 게임 개발, 네트워크 프로그래밍, 데이터베이스 관리 시스템 등 다양한 분야에서 사용됩니다. 또한, C언어를 기반으로 한 다른 프로그래밍 언어들도 많이 개발되었습니다.
•
C++: C언어의 기능을 확장하여 객체지향 프로그래밍 기능을 추가한 언어입니다. C++은 C언어의 문법과 구조를 거의 그대로 사용하며, C언어와의 호환성이 높은 언어입니다.
•
C#: C++의 문법을 기반으로 하여 마이크로소프트에서 개발한 객체지향 프로그래밍 언어입니다. Windows 운영체제와 밀접한 연관이 있으며, .NET 프레임워크에서 사용됩니다.
•
Python: C언어와 달리 코드를 간결하게 작성할 수 있는 인터프리터 언어입니다. C언어와 마찬가지로 다양한 운영체제에서 사용할 수 있습니다.
•
Java: C언어와 비슷한 문법을 가지고 있으며, 객체지향 프로그래밍 언어입니다. Java는 C언어와 달리 운영체제에 독립적으로 실행될 수 있도록 설계되었습니다.
•
PHP: 서버 측 웹 개발에 많이 사용되는 언어 중 하나입니다. C언어와 문법적으로 유사하며, 웹 페이지에서 동적인 콘텐츠를 생성할 수 있습니다.
•
JavaScript: 웹 페이지에서 동적인 기능을 추가하기 위해 사용되는 스크립트 언어입니다. C언어와 문법적으로 비슷하지만, 객체지향 프로그래밍 기능도 지원합니다.
•
Rust: C언어의 보안적인 문제를 해결하기 위해 메모리 관리와 보안성을 강조하는 언어입니다. 최근 들어 각광받고 있으며 여러 분야에서 적용이 이루어지고 있습니다.
C vs Python
[2023 방통대 C 스터디] 1. C언어와 친해지기