<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>resister_devlog</title>
        <link>https://velog.io/</link>
        <description>좋은 제품을 만드는 사람</description>
        <lastBuildDate>Sun, 04 Dec 2022 04:03:09 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>resister_devlog</title>
            <url>https://velog.velcdn.com/images/resister_boy/profile/6808c369-9cf7-4f32-9666-a494a8fa4e15/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. resister_devlog. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/resister_boy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[atoi() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/atoi-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/atoi-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 04 Dec 2022 04:03:09 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;stdlib.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int    atoi(const char *str);</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>const char *str: 숫자로 바꾸어 반환할 char 포인터 str</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>atoi()는 char 포인터 str을 인자로 받아 공백 문자를 제거하고, 부호를 계산한 후 char 타입의 숫자를 int 타입의 숫자로 바꾸어 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>atoi()는 char 포인터 str를 인자로 받아 공백 문자를 제거하고, 부호를 계산한 후 char 타입의 숫자를 int 타입의 숫자로 바꾸어 반환합니다. 이때 인자로 받는 char 포인터가 가리키는 값은 상수이기 때문에 변경할 수 없습니다. </p>
</blockquote>
<blockquote>
<p>atoi()는 공백문자의 개수와 상관없이 모든 공백문자를 건너 뛰지만, 부호 또는 숫자 이후에 등장하는 공백문자는 계산할 수 없습니다. 즉, 부호와 숫자 앞에 위치한 공백 문자만 건너뛸 수 있으며, 중간에 공백문자가 등장할 경우 함수가 종료됩니다. </p>
</blockquote>
<blockquote>
<p>atoi()는 부호는 하나만 계산할 수 있습니다. 즉, &#39;+&#39;나 &#39;-&#39;를 각각 하나씩만 받을 수 있으며, &#39;+-&#39;나 &#39;--&#39;와 같은 부호는 입력받을 없습니다. 만일 이와 같은 방식의 부호를 입력받을 경우 함수가 종료됩니다.</p>
</blockquote>
<blockquote>
<p>atoi()는 공백 문자와 부호, 그리고 ASCII 코드 상 숫자로 표현할 수 없는 숫자가 있을 경우 함수가 종료됩니다. 즉, char 포인터가 가리키는 문자열에 공백 문자와 부호, 숫자 이외의 문자가 있을 경우 해당하는 문자를 만나게 되면 함수가 종료됩니다.</p>
</blockquote>
<blockquote>
<p>atoi()의 반환값은 숫자지만, atoi()의 원형은 인자로 받은 char 포인터를 strtod()에 넣어 반환합니다. 이때 strtod()는 double 타입을 반환합니다. 이때, int 타입은 4byte만큼의 숫자만 표현할 수 있는 반면, double 타입은 8byte만큼에 숫자까지 표현할 수 있기 때문에 숫자가 int 타입의 범위를 초과할 경우를 고려하여 같은 8byte 자료형인 long long int타입으로 반환해줍니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li><p>부호의 상태를 관리해줄 변수 sign과 문자를 숫자로 바꾸어 반환할 변수 value를 선언해줍니다.</p>
</li>
<li><p>변수 sign은 1, value는 2로 초기화해줍니다. </p>
</li>
<li><p>인자로 받은 char 포인터가 가리키는 문자열을 돌면서 공백문자가 있는 경우 모두 건너뛰어줍니다. </p>
</li>
<li><p>공백문자를 모두 건너뛴 후 부호가 있는 경우에도 모두 건너뛰어줍니다. </p>
</li>
<li><p>만일 &#39;-&#39;를 만나게 되면 변수 sign에 -1을 곱해줍니다. </p>
</li>
<li><p>숫자를 만나게 될 경우 char 타입의 숫자에 -48을 하여 int 타입의 숫자로 만들어줍니다.</p>
</li>
<li><p>숫자를 만날 때마다 * 10를 해주어 이전에 만난 숫자들의 자릿수를 올려줍니다.</p>
</li>
<li><p>변수 sign과 변수 value를 곱한 값을 반환합니다. </p>
</li>
</ol>
<pre><code class="language-c">int    my_atoi(const char *str)
{
    long long int    sign;
    long long int    value;

    sign = 1;
    value = 0;
    while (*str == &#39;\t&#39; || *str == &#39;\n&#39; || *str == &#39;\v&#39; \
            || *str == &#39;\f&#39; || *str == &#39;\r&#39; || *str == &#39; &#39;)
        str++;
    if (*str == &#39;+&#39; || *str == &#39;-&#39;)
    {
        if (*str == &#39;-&#39;)
            sign *= -1;
        str++;
    }
    while (*str &gt;= 48 &amp;&amp; *str &lt;= 57)
    {
        value *= 10;
        value += *str - 48;
        str++;
    }
    return (value * sign);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[tolower() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/tolower-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/tolower-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 04 Dec 2022 03:07:30 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int    tolower(int c)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int c: 소문자로 바꾸어 반환할 숫자 c</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>tolower()는 숫자를 인자로 받아 만일 숫자의 ASCII값이 대문자 알파벳인 경우 이를 소문자로 바꾸어 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>tolower()는 숫자를 인자로 받아 만일 숫자 c의 ASCII값이 대문자 알파벳에 해당하는 65 ~ 90인 경우 이를 소문자로 바꾸어 반환합니다. 만일 인자로 받은 숫자가 대문자 알파벳에 해당하는 숫자가 아닌 경우 인자로 받은 숫자 c를 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 c가 65 ~ 90에 해당하는 경우 c + 32를 반환합니다.<pre><code class="language-c">int my_tolower(int c) {
 if (c &gt;= 65 &amp;&amp; c &lt;= 90)
     c += 32;
 return (c);
}</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[toupper() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/toupper-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/toupper-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Nov 2022 08:56:34 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int toupper(int c);</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int c: 대문자로 바꾸어 반환할 숫자 c</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>toupper()는 숫자를 인자로 받아 만일 숫자의 ASCII값이 소문자 알파벳에 해당하는 경우 경우 이를 알파벳 대문자로 바꾸어 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>toupper()는 숫자를 인자로 받아 만일 숫자 c의 ASCII값이 소문자 알파벳에 해당하는 97 ~ 122인 경우 이를 대문자로 바꾸어 반환합니다. 만일 이자로 받은 숫자가 소문자 알파벳에 해당하는 숫자가 아닌 경우 인자로 받은 숫자 c를 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 c가 97 ~ 122에 해당하는 경우 c - 32를 반환합니다.</li>
</ol>
<pre><code class="language-c">int    my_toupper(int c) {
    if (c &gt;= 97 &amp;&amp; c &lt;= 122)
        num -= 32;
    return (c);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 - Makefile에 대하여]]></title>
            <link>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Makefile%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Makefile%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Fri, 18 Nov 2022 12:32:28 GMT</pubDate>
            <description><![CDATA[<h1 id="make란-무엇일까">make란 무엇일까?</h1>
<p>GNU make를 개발한 GNU에서는 make를 다음과 같이 소개하고 있습니다.</p>
<blockquote>
<p>The make utility automatically determines which pieces of a large program need to be recompiled, and issues commands to recompile them.</p>
</blockquote>
<blockquote>
<p>make 유틸리티는 다시 컴파일 해야하는 대형 프로그램 부분을 자동으로 판별하고 이를 다시 컴파일하는 명령을 실행합니다.</p>
</blockquote>
<p>규모가 큰 프로그램을 개발할 때는 하나의 파일을 여러 개로, 모듈을 나누어 진행하게 됩니다. 만일 make를 사용하지 않을 경우 여러 개의 소스 코드를 하나씩 빌드해야 해야 합니다. 즉, 소스 코드를 오브젝트 코드로 변환하고 링크해서 실행 파일을 만들어야 한다는 것입니다.</p>
<p>여기까지만 하더라도 비효율적이지만, 만일 하나의 파일에 문제가 생겨 다시 컴파일을 해야한다면 어떨까요? 이 모든 작업을 처음부터 다시 해야만 합니다. 이때 사용하는 것이 바로 make입니다. </p>
<p>make는 여러 개의 모듈화된 소스 코드 파일을 빌드할 때 사용하는 프로그램 빌드 도구입니다. make는 여러 파일들 사이의 의존성과 각 파일에 필요한 명령을 정의함으로써 프로그램을 컴파일할 수 있으며, 최종 프로그램, 즉 실행 파일을 만드는데 필요한 명령어를 서술할 수 있는 표준 문법을 제공하고 있습니다. </p>
<h3 id="incremental-build">Incremental Build</h3>
<blockquote>
<p>Incremental Build는 make가 제공하는 강력한 기능 중 하나입니다. Incremental Build는 반복적인 빌드 과정에서 변경된 소스코드의 의존하고 있는 대상들만 다시 빌드하는 기능으로, 쉽게 말해 make 명령어를 사용하여 프로그램을 다시 빌드할 경우 makefile에 정의된 전체 명령어를 실행하는 것이 아니라, 수정된 코드와 연관된 명령어만 다시 실행하는 것이라고 할 수 있습니다.</p>
</blockquote>
<h1 id="makefile은-무엇일까">makefile은 무엇일까?</h1>
<p>makefile은 각 파일 사이의 의존성과 필요한 명령이 정의된 파일입니다. 즉, 최종 프로그램이 만들기 위해 필요한 명령어가 서술된 파일입니다. 대상(Target), 의존 관계(Dependency), 명령어(Recipe)로 구성됩니다.</p>
<pre><code class="language-c">&lt;Target&gt; : &lt;Dependency&gt;
(tab) &lt;Command&gt;</code></pre>
<h3 id="target">Target</h3>
<blockquote>
<p>명령어에 의해 생성되는 파일이며, 컴파일을 통해 만들어진 오브젝트 파일 또는 링킹을 통해 만들어진 실행 파일이 여기에 해당됩니다.</p>
</blockquote>
<h3 id="dependency">Dependency</h3>
<blockquote>
<p>Target을 생성할 때 필요한 파일, 다시 말해 Target이 의존하는 파일을 의미하며, 오브젝트 파일을 생성할 때 필요한 소스 파일 또는 실행 파일을 생성할 때 필요한 오브젝트 파일이 해당됩니다. 만일 Dependency(소스 파일 또는 오브젝트 파일)가 변경되었을 경우 Incremental Build 기능에 따라 변경된 Dependency에 의존하는 Target은 자동으로 다시 빌드됩니다.</p>
</blockquote>
<h3 id="recipe">Recipe</h3>
<blockquote>
<p>빌드 대상을 생성하는 명렁어를 의미하며, 여러 줄로 작성할 수 있고 ShellScript를 사용할 수도 있습니다. 명령어는 반드시  tab으로 들여쓰기를 한 후에 작성되어야 합니다.</p>
</blockquote>
<h1 id="makefile-작성하기">makefile 작성하기</h1>
<pre><code class="language-c">// &lt;Target&gt; : &lt;Dependency&gt;
//   &lt;Command&gt;

// 첫 번째 블록은 a.o b.o main.o(Dependency)를 통해 a.out(Target)을 생성합니다.
// a.out은 a.o b.o main.o에 의존합니다.
// a.out을 생성하기 위해 gcc -o a.out a.o b.o main.o 명령어가 실행됩니다.
a.out : a.o b.o main.o 
    gcc -o a.out a.o b.o main.o


// 두 번째 블록은 a.c(Dependency)를 통해 a.o(Target)을 생성합니다.
// a.o는 a.c에 의존합니다.
// a.o을 생성하기 위해 gcc -c -o a.o a.c 명령어가 실행됩니다.
a.o : a.c
    gcc -c -o a.o a.c

// 세 번째 블록은 b.c(Dependency)를 통해 b.o(Target)을 생성합니다.
// b.o는 b.c에 의존합니다.
// b.o을 생성하기 위해 gcc -c -o b.o b.c 명령어가 실행됩니다.
b.o : b.c
    gcc -c -o b.o b.c

// 네 번째 블록은 main.c(Dependency)를 통해 main.o(Target)을 생성합니다.
// main.o는 main.c에 의존합니다.
// main.o을 생성하기 위해 gcc -c -o main.o main.c 명령어가 실행됩니다.
main.o : main.c
    gcc -c -o main.o main.c

// 다섯 번째 블록에서는 makefile에서 macro를 정의합니다.
// 아래의 경우 make clean을 사용하면 make를 통해 만들어진 오브젝트 파일과 실행파일 a.out이 제거됩니다.
clean:
    rm *.o a.out</code></pre>
<blockquote>
<p>위 코드가 작성된 makefile이 존재하는 디렉토리 내에서 make를 실행합니다. make 명령어를 통해 정상적으로 빌드되었을 경우 아래와 같은 문구가 터미널에 나오게 됩니다.</p>
</blockquote>
<pre><code class="language-c">gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -c -o main.o main.c
gcc -o a.out a.o b.o main.o</code></pre>
<h1 id="변수를-활용한-makefile-작성">변수를 활용한 makefile 작성</h1>
<blockquote>
<p>makefile에서도 변수를 사용할 수 있습니다. make 표준문법에서는 make에서 사용할 수 있는 내장변수와 자동변수를 제공하고 있습니다. </p>
</blockquote>
<h3 id="make-내장변수">make 내장변수</h3>
<blockquote>
<p>make가 제공하는 내장변수는 [내장변수]=[변수명]과 같은 방식으로 정의하고, $()를 사용하여 호출할 수 있습니다. </p>
</blockquote>
<p><strong>CC</strong>: 컴파일러</p>
<p><strong>CFLAGS</strong>: 컴파일옵션</p>
<p><strong>OBJS</strong>: 최종 실행파일을 만들 때 함께 링킹할 오브젝트 파일들</p>
<p><strong>TARGET</strong>: 빌드 대상, 즉 실행파일</p>
<p><strong>LDFLAGS</strong>: 링커 옵션</p>
<p><strong>LDLIBS</strong>: 링크 라이브러리</p>
<blockquote>
<h4 id="make-내장변수의-선언과-사용">make 내장변수의 선언과 사용</h4>
</blockquote>
<pre><code class="language-c">CC=gcc
CFLAGS=-g -Wall
TARGET=a.out
OBJECTS=a.o b.o main.o

$(TARGET) : $(OBJS) 
    $(CC) -o $(TARGET) $(OBJS)

a.o : a.c
    $(CC) -c -o a.o a.c

b.o : b.c
    $(CC) -c -o b.o b.c

main.o : main.c
    $(CC) -c -o main.o main.c

clean:
    rm $(OBJS) $(TARGET)</code></pre>
<h3 id="make-자동변수">make 자동변수</h3>
<blockquote>
<p>make가 제공하는 자동변수는 특별히 선언할 필요없이 사용할 수 있습니다. 또한 사용할 때에도 $[자동변수]와 같은 방식으로 ()없이 사용할 수 있습ㄴ디ㅏ.</p>
</blockquote>
<p>$@: Target ex) a.out</p>
<p>$^: 모든 Dependency ex) a.o b.o main.o</p>
<p>$&lt;: 첫 번째 Dependency ex) a.o</p>
<p>$?: 변경된 Dependency ex) main.o</p>
<p>$*: Target의 이름 ex) a</p>
<blockquote>
<h4 id="make-자동변수의-선언과-활용">make 자동변수의 선언과 활용</h4>
</blockquote>
<pre><code class="language-c">CC=gcc
CFLAGS=-g -Wall
TARGET=a.out
OBJECTS=a.o b.o main.o

$@ : $^ 
    $(CC) -o $@ $^

a.o : a.c
    $(CC) -c -o a.o a.c

b.o : b.c
    $(CC) -c -o b.o b.c

main.o : main.c
    $(CC) -c -o main.o main.c

clean:
    rm $@ $^</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://ko.wikipedia.org/wiki/Make_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)">https://ko.wikipedia.org/wiki/Make_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)</a></p>
<p><a href="https://love-every-moment.tistory.com/47">https://love-every-moment.tistory.com/47</a></p>
<p><a href="https://velog.io/@woodstock1993/Makefile">https://velog.io/@woodstock1993/Makefile</a></p>
<p><a href="https://bowbowbow.tistory.com/12">https://bowbowbow.tistory.com/12</a></p>
<p><a href="https://www.gnu.org/software/make/manual/make.html">https://www.gnu.org/software/make/manual/make.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 - Compiling Process에 대하여]]></title>
            <link>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Compiling-Process%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Compiling-Process%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Fri, 18 Nov 2022 12:12:05 GMT</pubDate>
            <description><![CDATA[<h1 id="컴파일compile이란-무엇일까">컴파일(Compile)이란 무엇일까?</h1>
<p>컴파일(Compile)은 인간이 이해할 수 있는 언어로 작성된 소스 코드를 컴퓨터, 엄밀한 의미에서는 <strong>CPU</strong>가 이해할 수 있는 언어로 변환하는 작업을 말합니다. 소스 코드는 컴파일 과정을 거쳐 기계어로 이루어진 실행파일이되며, 이를 실행하면 실행 파일 내용이 <strong>운영체제의 Loeader</strong>에 의해 메모리(주기억장치)에 적재되고 실행됩니다.</p>
<h1 id="컴파일-과정compiling-process">컴파일 과정(Compiling Process)</h1>
<p>컴파일은 전처리(Pre-processing), 컴파일(Compilation), 어셈블(Assemble), 링킹(Link)이라는 4가지 단계로 구성되어있습니다. 일반적으로 이 4단계를 묶어서 컴파일(Compile) 또는 빌드(Build)라고 부르고 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/resister_boy/post/8582ab04-42fc-4138-9567-a939b8b97d3c/image.png" alt="Compiling Process"></p>
<h2 id="전처리pre-processing">전처리(Pre-processing)</h2>
<p>전처리 단계에서는 전처리기(Preprocessor)를 통해 소스코드(.c)를 전처리된 소스코드(.i)로 변환합니다. 전처리 단계에서는 다음과 같은 세 가지 작업을 수행합니다.</p>
<h3 id="1-주석-제거">1. 주석 제거</h3>
<blockquote>
<p>소스코드의 모든 주석을 제거합니다.</p>
</blockquote>
<h3 id="2-헤더파일-삽입">2. 헤더파일 삽입</h3>
<blockquote>
<p>#include 지시문을 만나면 이에 해당하는 헤더파일을 찾아 헤더파일에 있는 내용을 복사하여 소스코드에 삽입합니다. 즉, 헤더파일 자체는 컴파일되지 않고 소스코드 내에 전부 복사됩니다. 헤더파일에 선언된 함수원형은 나중에 링킹 단계에서 실제로 함수가 정의되어 있는 오브젝트 파일과 결합하게 됩니다. </p>
</blockquote>
<h3 id="3-매크로-치환-및-적용">3. 매크로 치환 및 적용</h3>
<blockquote>
<p>#define을 포함한 전처리 지시문을 통해 정의된 매크로(Macro)를 저장하고 소스코드에서 매크로를 만나면 미리 정의한 내용으로 치환합니다.</p>
</blockquote>
<h2 id="컴파일compilation">컴파일(Compilation)</h2>
<p>컴파일 단계에서는 컴파일러(Compiler)를 통해 전처리된 소스코드(.i)를 어셈블리 코드(.s)로 변환합니다. 이 과정에서 컴파일러는 언어의 문법을 검사하고 Static한 영역(Data, BSS)에 메모리가 할당됩니다. 컴파일 단계는 아래의 세 단계로 구성되어 있습니다. </p>
<h3 id="1-프론트앤드">1. 프론트앤드</h3>
<blockquote>
<p>프론트앤드에서는 언어 종속적인 부분을 처리합니다. 소스코다가 해당 언어로 올바르게 작성되었는지 확인하고 미들앤드에 넘겨주기 위한 GIMPLE TREE(소스코드를 트리 형태로 표현한 자료구조)를 생성합니다.</p>
</blockquote>
<h3 id="2-미들앤드">2. 미들앤드</h3>
<blockquote>
<p>미들앤드에서는 아키텍쳐에 종속되지 않는 최적화를 수행합니다. 이는 CPU 아키텍쳐에 상관없이 할 수 있는 최적화를 의미합니다. 최적화를 수행한 뒤에는 백앤드에서 사용하게 되는 RTL(Resister Transfer Language: 고수준 언어와 어셈블리 코드의 중간 형태)를 생성합니다.</p>
</blockquote>
<h3 id="3-백앤드">3. 백앤드</h3>
<blockquote>
<p>백앤드에서는 아키텍쳐에 종속되는 최적화를 수행합니다. 이는 아키텍쳐의 특성에 따라 수행하는 최적화를 의미합니다. 같은 기능을 수행하는 명령어라고 하더라도 CPU 아키텍쳐에 따라 효율적인 명령어로 대체하여 성능을 높이는 작업입니다. 이 최적화가 완료되면 어셈블리 코드가 생성되는데, 이는 최적화를 수행한 아키텍쳐만이 이해할 수 있는 코드가 되며, 다른 아키텍쳐로는 해석할 수 없습니다. </p>
</blockquote>
<h2 id="어셈블assemble">어셈블(Assemble)</h2>
<p> 어셈블(Assemble) 단계에서는 어셈블러(Assembler)를 통해 어셈블리 코드(.s)를 오브젝트 코드(.o)로 변환합니다. 오브젝트 코드는 기계어나 혹은 이에 RTL과 같은 바이너리 코드로 이루어져있습니다. 이때 오브젝트 파일 포맷이 등장합니다.</p>
<h3 id="오브젝트-파일-포맷">오브젝트 파일 포맷</h3>
<blockquote>
<p>오브젝트 파일 포맷은 오브젝트 코드와 관련된 데이터가 저장되는 일종의 양식입니다. 이전에는 개별 컴퓨터마다 고유의 포맷을 가지고 있었으나, 유닉스와 같은 운영체제가 출현하면서 COFF, ELF와 같은 포맷이 정의되면서 여러 시스템에서 사용되기 시작했습니다. 대표적으로 Linux와 MacOS에서는 ELF(Excutable and Linkng Format)이 사용되고, Windows의 경우 PE(Portable Executable)이 사용되고 있습니다. 오브젝트 파일 포맷은 기본적으로 아래와 같은 구조를 하고 있습니다. </p>
</blockquote>
<blockquote>
<p><strong>1. 오브젝트 파일 헤더(Object File Header)</strong>
오브젝트 파일의 기본정보를 가지고 있는 헤더</p>
</blockquote>
<blockquote>
<p><strong>2. 텍스트 섹션(Text Section)</strong>
기계어 또는 RTL과 같은 바이너리 코드를 가지고 있는 섹션</p>
</blockquote>
<blockquote>
<p><strong>3. 데이터 섹션(Data Section)</strong>
데이터(전역 변수, 정적 변수)를 가지고 있는 섹션</p>
</blockquote>
<blockquote>
<p><strong>심볼 테이블 섹션(Symbol Table Section)</strong>
소스 코드에서 참조하는 심볼의 이름과 주소가 정의되어 있는 섹션 </p>
</blockquote>
<blockquote>
<p><strong>재배치 정보 섹션(Relocation Information Section)</strong>
링킹 전까지 심볼의 위치를 확정할 수 없으므로 심볼의 위치가 확정될 때 바꾸어야 할 내용이 정의되어 있는 섹션</p>
</blockquote>
<blockquote>
<p><strong>디버깅 정보 섹션(Debugging Information Section)</strong>
디버깅에 필요한 정보가 정의되어 있는 섹션</p>
</blockquote>
<p>여기에서 중요한 부분은 심볼 테이블 섹션과 재배치 정보 섹션이다. 심볼(Symbol)은 함수나 변수를 식별할 때 사용하는 이름으로 심볼 테이블 안에는 오브젝트 코드에서 참조하고 있는 심볼의 정보(이름과 메모리 주소)를 가지고 있습니다. 이때 오브젝트 코드가 있는 각 파일은 해당 파일의 심볼 정보만 가지고 있기 때문에 다른 파일에서 참조하는 심볼의 정보에는 접근할 수 없습니다. </p>
<p>여기까지 소스 코드를 컴파일하여 어셈블리 코드로 변환하고 이를 어셈블러를 통해 오브젝트 코드로 변환했습니다. 이제 오브젝트 코드를 실행파일로 만들면 소스코드를 실행할 수 있게 됩니다. 이제 링크(Link) 단계가 남았습니다.</p>
<p>만일 우리가 하나의 소스코드만을 가지고 이 작업을 진행했다면, 링크 단계가 필요하지 않겠지만, 여러 개의 파일에 코드가 모듈화되어있다면, 링크 단계를 거쳐야 실행파일이 될 수 있습니다. 이는 각 파일이 해당 파일의 심볼 정보만 가지고 있기 때문에 여러 개의 파일이 서로 의존하는 경우 정상적으로 빌드가 되지 않기 때문입니다. 마지막으로 링크(Link) 단계를 살펴보겠습니다. </p>
<h2 id="링크link">링크(Link)</h2>
<p>링크(Link) 단계에서는 링커(Linker)를 통해 여러 개의 오브젝트 코드(.o)와 라이브러리 파일을 링크하여 하나의 실행파일을 생성합니다. 이때 라이브러리를 링크하는 방법에 따라 정적 링킹(Static Linking)과 동적 링킹(Dynamic Linking)으로 나뉘게 되며, 정적으로 링킹하는 라이브러리를 정적 라이브러리라고 하고, 동적으로 링킹하는 라이브러리를 동적 라이브러리라고 합니다. </p>
<h3 id="정적-라이브러리static-library">정적 라이브러리(Static Library)</h3>
<blockquote>
<p>정적 라이브러리는 정적 링킹 과정에서 링커가 프로그램이 실행되는데 필요한 부분을 라이브러리에서 찾아 실행 파일에 복사하는 방식의 라이브러리를 의미합니다.</p>
</blockquote>
<h3 id="동적-라이브러리dynamic-library">동적 라이브러리(Dynamic Library)</h3>
<blockquote>
<p>동적 라이브러리는 동적 링킹 과정에서 링커가 라이브러리의 내용을 복사하지 않고 해당 내용의 주소만 가지고 있다가 런타임에 실행 파일과 라이브러리가 메모리에 위치될 때 해당 모듈의 주소로 가서 필요한 것들을 가져오는 방식의 라이브러리를 의미합니다.</p>
</blockquote>
<h3 id="링커의-역할">링커의 역할</h3>
<h4 id="심볼-해석symbol-resolution">심볼 해석(Symbol Resolution)</h4>
<blockquote>
<p>심볼 해석(Symbol Resolution)은 각 오브젝트 파일의 심볼 테이블에 위치한 심볼의 정보를 연결시키는 과정을 말합니다. 여러 개의 오브젝트 파일에 같은 이름의 함수 또는 변수가 정의되어 있을 때 어떤 파일의 어떤 함수를 사용할지 결정하는 역할을 합니다.</p>
</blockquote>
<h4 id="재배치relocation">재배치(Relocation)</h4>
<blockquote>
<p>재배치(Relocation)은 오브젝트 파일에 있는 데이터의 주소나 코드의 메모리 코드의 메모리 참조 주소를 배치하는 과정을 말합니다. 링커가 컴파일러가 생성한 오브젝트 파일을 모아 하나의 하나의 실행 파일을 생성할 때, 각 오브젝트 파일에 있는 데이터의 주소나 코드의 메모리 참조 주소가 링커에 의해 합쳐진 실행 파일에서의 주소와 다르기 때문에 이를 수정해주는 것이라고 할 수 있습니다. 이것을 위해 오브젝트 파일 안에 재배치 정보 섹션(Relocation Information Section)이 존재하는 것이며, 이 과정에서 같은 세션끼리 합쳐진 후 재배치가 일어납니다.</p>
</blockquote>
<h2 id="conclusion">Conclusion</h2>
<p>이렇게 우리의 소스코드는 전처리, 컴파일, 어셈블, 링크라는 4단계를 거쳐 실행파일이 됩니다. 각 과정에서 소스코드는 전처리된 소스코더, 어셈블리 코드, 오브젝트 코드, 마지막으로 기계어로 변환되어 실행됩니다. 이렇게 C언어가 컴파일 되는 과정을 적어보았지만, 아직까지 개괄적인 내용이라고 생각합니다. 아직까지 전처리 우선순위나 오브젝트 파일 포맷과 심볼 등 공부해야 할 것이 많은 것 같습니다. 이 글은 아래 링크들을 참조하여 작성되었습니다. 틀린 부분이 있다면 댓글로 남겨주세요.</p>
<h3 id="reference">Reference</h3>
<p><a href="https://bradbury.tistory.com/226">https://bradbury.tistory.com/226</a></p>
<p><a href="https://reakwon.tistory.com/52">https://reakwon.tistory.com/52</a></p>
<p><a href="https://gracefulprograming.tistory.com/16">https://gracefulprograming.tistory.com/16</a></p>
<p><a href="https://www.it-note.kr/263">https://www.it-note.kr/263</a></p>
<p><a href="https://ko.wikipedia.org/wiki/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC">https://ko.wikipedia.org/wiki/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC</a></p>
<p><a href="https://blog.naver.com/PostView.naver?blogId=techref&amp;logNo=222221869206&amp;from=search&amp;redirect=Log&amp;widgetTypeCall=true&amp;directAccess=false">https://blog.naver.com/PostView.naver?blogId=techref&amp;logNo=222221869206&amp;from=search&amp;redirect=Log&amp;widgetTypeCall=true&amp;directAccess=false</a></p>
<p><a href="https://simsimjae.tistory.com/235">https://simsimjae.tistory.com/235</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 - Macro에 대하여]]></title>
            <link>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Macro%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-Macro%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Fri, 18 Nov 2022 04:59:29 GMT</pubDate>
            <description><![CDATA[<h3 id="매크로macro란-무엇일까">매크로(Macro)란 무엇일까?</h3>
<blockquote>
<p>매크로(Macro)는 특정 코드(자주 사용하는)를 하나의 명령어로 묶어 코드를 더 단순하고 간결하게 작성할 수 있도록 하는 문법입니다. 매크로를 사용할 경우 코드의 가독성을 높일 수 있을 뿐 아니라 매크로를 수정하면 소스 코드 전체에 수정된 내용이 반영되기 때문에 유지보수 측면에서도 효율적입니다.</p>
</blockquote>
<h3 id="매크로-정의하는-법">매크로 정의하는 법</h3>
<blockquote>
<p>매크로는 #define을 사용하여 정의하며 일반적으로 소스 코드의 제일 상단에 위치합니다. 이는 C 컴파일러가 소스 파일의 상단에서부터 컴파일하는데, 만일 매크로가 정의되기 이전에 사용될 경우 에러가 발생하기 때문입니다. 또한 매크로를 선언할 때는 보통 대문자로 선언하는데 이는 코드의 가독성 때문입니다. 매크로는 #define 이후 정의되는 명령어에 따라 매크로 상수와 매크로 함수로 구분되며, 매크로 상수와 매크로 함수는 아래와 같이 정의합니다.</p>
</blockquote>
<h4 id="매크로-상수">매크로 상수</h4>
<pre><code class="language-c">// #define [매크로 상수명] [값]
#define AGE 22 
#define NAME &quot;Resister_boy&quot;
#define WEIGHT 90

int main() {
    printf(&quot;My Age is %d\n&quot;, AGE); // AGE는 전처리 과정에서 22로 치환
    printf(&quot;My Name is %s\n&quot;, NAME); // NAME은 전처리 과정에서 Resister_boy로 치환
    printf(&quot;My Weight is %d\n&quot;, WEIGHT); // WEIGHT은 전처리 과정에서 90으로 치환
    return (0);
}</code></pre>
<h4 id="매크로-함수">매크로 함수</h4>
<pre><code class="language-c">// #define [매크로 함수명[인자]] [명령어]
#include &lt;stdio.h&gt; // 매크로에서 표준함수를 사용하려면 해당 함수원형이 선언된 헤더파일을 선언해야 한다
#define PLUS(X) ((X)+(X))
#define MINUS(Y) ((Y)-(Y))
#define MULTIPLY(Z) ((Z)*(Z))
#define PRINTVALUE(X, Y, Z) printf(&quot;PLUS : %d\nMINUS : %d\nMULTIPLY : %d&quot;, X, Y, Z);

int main(void) {
    int x = 1;
    int y = 5;
    int z = 10;

    int _x;
    int _y;
    int _z;

    _x = PLUS(x);
    _y = MINUS(y);
    _z = MULTIPLY(z);

    PRINTVALUE(_x, _y, _z);
    return (0);
}</code></pre>
<blockquote>
<p>매크로 함수의 역할 자체는 전역적으로 선언된 함수와 비슷하다고 할 수 있습니다. 매크로 함수는 컴파일러가 소스 코드를 컴파일 하기 이전에 전처리 과정에서 매크로로 선언된 값이 소스 코드에서 매크로가 사용된 위치로 치환된다는 차이가 있습니다. 매크로 함수가 컴파일 되기 이전 전처리 단계에서 치환된다는 것은 매크로 함수의 중요한 특징입니다. 이때 유의해야 할 점은 매크로 함수가 컴파일 이전에 미리 치환되는데, 때문에 매크로 함수를 사용할 때는 괄호()를 사용하여 함수와 모든 인자를 묶어주어야 합니다.</p>
</blockquote>
<blockquote>
<p>매크로 함수는 코드를 연산하는 것이 아니라 단순히 치환만 해주는 것이기 때문에 인수의 타입을 체크하지 않으며, 동시에 여러 개의 명령문을 포함할 수 있습니다. 또한 함수 호출에 의한 성능 저하가 일어나지 않기 때문에 실행속도가 향상된다는 장점이 있습니다. 다만, 복잡한 함수의 구현과 디버깅이 어려우며, 추상화된 계층이 하나 더 생겨나는 것이기 때문에 코드를 읽고 이해하기 까다롭다는 단점이 있습니다.</p>
</blockquote>
<h3 id="조건부-매크로-정의">조건부 매크로 정의</h3>
<blockquote>
<p>일반적으로 매크로를 정의할 때는 #define을 사용하지만, 조건에 따라 매크로를 선언할 수 있도록 하는 명령어도 있습니다. 이 경우 조건에 해당하지 않을 경우 매크로가 컴파일되지 않으며, 이는 소스 자체가 존재하지 않는 것과 같습니다. 이를 전처리 명령어라고 합니다.</p>
</blockquote>
<h4 id="if">#if</h4>
<blockquote>
<p>#if 오른쪽 조건이 참일 경우 아래 명령어를 컴파일합니다</p>
</blockquote>
<pre><code class="language-c">#if NUMBER &lt;= 10
    printf(&quot;%d\n&quot;, NUMBER) // NUMBER가 10이하일 때 NUMBER를 출력</code></pre>
<h4 id="elif">#elif</h4>
<blockquote>
<p>#elif 오른쪽 조건이 참일 경우 아래 명령어를 컴파일합니다</p>
</blockquote>
<pre><code class="language-c">#elif NUMBER &gt;= 20
    printf(&quot;%d\n&quot;, NUMBER) // NUMBER가 20이상일 때 NUMBER를 출력</code></pre>
<h4 id="else">#else</h4>
<blockquote>
<p>#if 또는 #elif가 참이 아닐 경우 아래 명령어를 컴파일합니다</p>
</blockquote>
<pre><code class="language-c">#else
    printf(&quot;%d\n&quot;, NUMBER) // NUMBER가 11이상이고 20미만일 때 NUMBER를 출력</code></pre>
<h4 id="ifdef">#ifdef</h4>
<blockquote>
<p>오른쪽 매크로 또는 파일이 정의되어 있을 경우 아래 명령어를 컴파일합니다</p>
</blockquote>
<pre><code class="language-c">#ifdef NUMBER
    printf(&quot;%d\n&quot;, NUMBER) // NUMBER가 정의되어 있을 경우 NUMBER를 출력</code></pre>
<h4 id="ifndef">#ifndef</h4>
<blockquote>
<p>오른쪽 매크로 또는 파일이 정의되어 있지 않을 경우 아래 명령어를 컴파일합니다</p>
</blockquote>
<pre><code class="language-c">#ifndef NUMBER
#define NUMBER 10 // NUMBER가 정의되어 있지 않을 경우 아래 NUMBER 10을 정의</code></pre>
<h4 id="endif">#endif</h4>
<blockquote>
<p>조건부 매크로 정의 후 전처리 명령어가 끝났음을 정의하는 명령어입니다.</p>
</blockquote>
<pre><code class="language-c">#endif</code></pre>
<h3 id="매크로-정의-해제">매크로 정의 해제</h3>
<blockquote>
<p>#undef 전처리 명령어를 통해 정의한 매크로를 해제할 수 있습니다.</p>
</blockquote>
<pre><code class="language-c">#undef NUMBER // 정의된 매크로 NUMBER를 해제</code></pre>
<h3 id="reference">Reference</h3>
<ul>
<li><p>코딩교육 TCP School
<a href="http://www.tcpschool.com/c/c_prepro_macroFunc">http://www.tcpschool.com/c/c_prepro_macroFunc</a></p>
</li>
<li><p>C전처리기 - 위키백과
<a href="https://ko.wikipedia.org/wiki/C_%EC%A0%84%EC%B2%98%EB%A6%AC%EA%B8%B0">https://ko.wikipedia.org/wiki/C_%EC%A0%84%EC%B2%98%EB%A6%AC%EA%B8%B0</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[strlen() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/strlen-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/strlen-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Nov 2022 04:39:49 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;string.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int strlen(char *str)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>char *str : 길이를 계산할 문자열 포인터 str</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>strlen()은 문자열 포인터를 인자로 받아 인자로 받은 문자열의 길이를 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>strlen()은 문자열 포인터를 인자로 받아 인자로 받은 문자열의 길이를 반환합니다. 이때 문자열의 길이는 문자열을 구성하는 문자의 개수를 의미하며, 문자의 개수는 인자로 받은 문자열 포인터부터 null 문자까지로 계산합니다. 때문에 null 문자는 문자열의 길이를 계산할 때 포함되지 않습니다. </p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 문자열의 인덱스에 접근하기 위한 숫자 len을 선언합니다.</li>
<li>while문을 선언하고 문자열의 값이 null 문자가 아닐 때 동작하도록 조건을 선언합니다.</li>
<li>숫자 len은 0부터 시작하여 문자열의 값이 null 문자가 나올 때까지 문자열을 순회합니다.</li>
<li>결과적으로 while문이 반복한 만큼 숫자 len이 1씩 증가하며 이는 문자의 개수만큼 반복했기 때문에 len은 문자열의 길이가 됩니다.</li>
<li>문자열의 길이 len을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_strlen(char *str) {
    int len;

    len = 0;
    while (str[len] != &#39;\0&#39;)
        len++;
    return (len);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/strlen.3.html">https://man7.org/linux/man-pages/man3/strlen.3.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[isprint() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/isprint-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/isprint-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Nov 2022 04:35:26 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int isprint(int num)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int num : 출력 가능한 문자인지, 출력할 수 없는 문자인지 판별할 숫자 num</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>isprint()는 인자로 받은 숫자가 출력 가능한 ASCII 문자에 해당하는 경우 숫자 1, 인자로 받은 숫자가 출력 불가능한 ASCII 문자에 해당하는 경우 숫자 0을 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>isprint()는 인자가 출력할 수 있는 숫자인지 판별합니다. int 타입을 인자로 받으며, 인자로 받은 숫자의 ASCII 값을 기준으로 판별하여 값을 반환합니다. 만일 인자로 받은 숫자가 33 ~ 126인 경우 이는 ASCII 코드 상 출력가능한 문자에 해당하여 1을 반환합니다. 만일 인자로 받은 숫자가 위에 해당하지 않을 경우 0을 리턴합니다. ASCII 코드 상 0부터 32, 그리고 127은 출력 불가능한 문자에 해당합니다. 만일 인자가 ASCII 문자로 표현될 수 없는 127을 초과하는 숫자일 경우에도 숫자 0을 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 출력 가능한 문자(ASCII 33 ~ 126)에 해당할 경우 1을 반환합니다.</li>
<li>인자로 받은 숫자가 출력 불가능한 문자일 경우 0을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_isprint(int num) {
    if (num &gt; 32 &amp;&amp; num &lt; 127)
        return (1);
    return (0);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/isprint.3p.html">https://man7.org/linux/man-pages/man3/isprint.3p.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[isascii() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/isascii-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/isascii-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Nov 2022 04:32:06 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int isascii(int num)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int num : ASCII 문자로 표현 가능한지 판별할 숫자 num</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>isascii()는 인자가 ASCII 문자로 표현할 수 있는 숫자일 경우 숫자 1, ASCII 문자로 표현할 수 없는 숫자일 경우 숫자 0을 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>isascii()는 인자가 ASCII 문자로 표현될 수 있는 숫자인지 판별합니다. int 타입을 인자로 받으며, 인자로 받은 숫자의 ASCII 값을 기준으로 판별하여 값을 반환합니다. 만일 인자로 받은 숫자가 0 ~ 127에 해당하는 경우 이는 ASCII 문자로 표현될 수 있기 때문에 1을 반환합니다. 만일 인자로 받은 숫자가 위에 해당하지 않을 경우 0을 반환합니다. 이때 적용되는 ASCII 코드는 확장 아스키코드가 아니며, 때문에 127 이상의 숫자를 입력할 경우에도 0을 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 num이 ASCII 문자로 표현할 수 있는 숫자(ASCII 0 ~ 127)에 해당할 경우 1을 반환합니다.</li>
<li>인자로 받은 숫자 num이 ASCII 문자로 표현할 수 없는 숫자일 경우 0을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_isascii(int num) {
    if (num &gt;= 0 &amp;&amp; &lt;= 127)
            return (1);
    return (0);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/isascii.3p.html">https://man7.org/linux/man-pages/man3/isascii.3p.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[isalnum() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/isalnum-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/isalnum-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Nov 2022 04:28:47 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int isalnum(int num)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int num : 알파벳인지, 숫자인지 판별할 숫자 num</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>isalnum()은 인자가 알파벳 또는 숫자일 경우 숫자 1, 인지가 알파벳 또는 숫자가 아닐 경우 숫자 0을 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>isalnum()은 인자가 알파벳 또는 숫자인지 아닌지 판별합니다. int 타입을 인자로 받으며, 인자로 받은 숫자의 ASCII 값을 기준으로 판별하여 값을 반환합니다. 만일 인자로 받은 숫자가 65 ~ 90 또는 97 ~ 122일 경우 이는 알파벳 A ~ Z에 해당하여 1을 반환합니다. 만일 인자로 받은 숫자가 48 ~ 57일 경우 이는 숫자 0 ~ 9에 해당하여 역시 1을 반환합니다.  만일 인자로 받은 숫자가 위에 해당하지 않을 경우 0을 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 num이 알파벳(ASCII 65 ~ 90 또는 ASCII 97 ~ 122)에 해당할 경우 1을 반환합니다.</li>
<li>인자로 받은 숫자 num이 숫자(ASCII 48 ~ 57)에 해당할 경우 1를 반환합니다.</li>
<li>인자로 받은 숫자 num이 알파벳 또는 숫자에 해당하지 않을 경우 0을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_alnum(int num) {
    if((num &gt;= 48 &amp;&amp; num &lt;= 57)
        || num &gt;= 65 &amp;&amp; &lt;= 90)
        || num &gt;= 97 &amp;&amp; &lt;= 122))
        return (1);
    return (0);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/isalnum.3p.html">https://man7.org/linux/man-pages/man3/isalnum.3p.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[isdigit() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/isdigit-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/isdigit-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Nov 2022 04:23:45 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int isdigit(int num)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int num : 숫자인지 아닌지 판별할 숫자 num</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>isdigit()는 인자가 숫자일 경우 숫자 1, 인자가 숫자가 아닐 경우 숫자 0을 반환합니다.</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>isdigit()는 인자가 숫자인지 아닌지 판별합니다. int 타입을 인자로 받으며, 인자로 받은 숫자의 ASCII 값을 기준으로 판별하여 값을 반환합니다. 만일 인자로 받은 숫자가 48 ~ 57일 경우 이는 숫자 0 ~ 9에 해당하여 1을 반환합니다. 만일 인자로 받은 숫자가 위에 해당하지 않을 경우 0을 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 num이 숫자(ASCII 48 ~ 57)에 해당할 경우 1을 반환합니다.</li>
<li>인자로 받은 숫자 num이 숫자에 해당하지 않을 경우 0을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_isdigit(int num) {
    if (num &gt;= 48 &amp;&amp; num &lt;= 57)
            return (1);
    return (0);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/isdigit.3p.html">https://man7.org/linux/man-pages/man3/isdigit.3p.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[isalpha() 구현하기]]></title>
            <link>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-isalpha-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@resister_boy/C%EC%96%B8%EC%96%B4-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-isalpha-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 17 Nov 2022 18:24:26 GMT</pubDate>
            <description><![CDATA[<h3 id="header">Header</h3>
<blockquote>
<p>&lt;ctype.h&gt;</p>
</blockquote>
<h3 id="prototype">Prototype</h3>
<pre><code class="language-c">int isalpha(int num)</code></pre>
<h3 id="arguments">Arguments</h3>
<blockquote>
<p>int num : 알파벳인지 아닌지 판별할 숫자 num</p>
</blockquote>
<h3 id="return-value">Return Value</h3>
<blockquote>
<p>isaplha()는 인자가 알파벳 대문자일 경우 숫자 1, 인자가 알파벳 소문자일 경우 숫자 2, 인자가 알파벳이 아닐 경우 숫자 0을 반환합니다</p>
</blockquote>
<h3 id="description">Description</h3>
<blockquote>
<p>isalpha()는 인자가 알파벳인지, 만일 알파벳이라면 대문자인지, 소문자인지 판별합니다. 숫자 타입을 인자로 받으며, 인자로 받은 숫자의 ASCII 값을 기준으로 판별하여 값을 반환합니다. 만일 인자로 받은 숫자가 65 ~ 90일 경우 이는 알파벳 대문자 A ~ Z에 해당하여 1을 반환합니다. 만일 인자로 받은 숫자가 97 ~ 122일 경우 이는 알파벳 소문자 a ~ z에 해당하여 2를 반환합니다. 만일 인자로 받은 숫자가 위에 해당하지 않을 경우 0을 반환합니다.</p>
</blockquote>
<h3 id="code">Code</h3>
<ol>
<li>인자로 받은 숫자 num이 알파벳 대문자(ASCII 65 ~ 90)에 해당할 경우 1을 반환합니다.</li>
<li>인자로 받은 숫자 num이 알파벳 소문자(ASCII 97 ~ 122)에 해당할 경우 2를 반환합니다.</li>
<li>인자로 받은 숫자 num이 알파벳에 해당하지 않을 경우 0을 반환합니다.</li>
</ol>
<pre><code class="language-c">int my_isalpha(int num) {
    if (num &gt;= 65 &amp;&amp; num &lt;= 90)
            return (1);
    else if (num &gt;= 97 &amp;&amp; num &lt;= 122)
            return (2);
    return (0);
}</code></pre>
<h3 id="reference">Reference</h3>
<p><a href="https://man7.org/linux/man-pages/man3/isspace.3.html">https://man7.org/linux/man-pages/man3/isspace.3.html</a></p>
]]></description>
        </item>
    </channel>
</rss>