<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>업글인간의 정보 리뷰</title>
    <link>https://elevate-yourself.tistory.com/</link>
    <description>프로그래밍 및 독서와 같은 자기발전을 위한 정보를 공유하는 블로그입니다!</description>
    <language>ko</language>
    <pubDate>Tue, 14 Apr 2026 18:28:03 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>업글</managingEditor>
    <item>
      <title>TCP/IP 패킷 수신(패킷 분리 및 합침)</title>
      <link>https://elevate-yourself.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 TCP/IP 통신에 대한 예제들은 구글링을 통해서 쉽게 찾을 수 있습니다. 그러나 기본적인 함수 사용에 대한 내용이므로 바로 프로젝트 또는 현업에 적용하는 것은 쉽지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 포스팅에서는&amp;nbsp;TCP/IP 통신에서 패킷 수신 시 고려사항과 해당 사항을 고려한 로직 및 C/C++ 기반의 코드에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/IP 통신은 MSS 사이즈, 윈도우 사이즈, 네이글 알고리즘 등과 같은 특징들에 의해서 상대측 어플리케이션 레벨에서 송신한 패킷이 분리되거나 합쳐져서 송신되어 수신 시에 분리되거나 합쳐져서 수신되는 경우가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;패킷 분리되는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; data-alt=&quot;abcdef 송신&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnI9vx%2FbtrnB8hXfjy%2FaIsjkMZSHB6Mx6bKkuzbI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;144&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;abcdef 송신&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; data-alt=&quot;abc, def로 분리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQafE2%2FbtrnHSLtJDC%2FdI1ywAKvepq4800jru0BaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;654&quot; height=&quot;136&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;abc, def로 분리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림은 패킷 분리에 대한 예시로 상대측 어플리케이션 레벨에서 한번에 abcdef를 송신하였는데 수신 함수를 통해서 첫번째 수신하였을 때는 abc, 두번째 수신하였을 때는 def가 수신되는 경우입니다. TCP 관련 Layor를 통해서 abc, def로 분리된 후 송신되어 분리된 패킷을 수신하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;패킷 합쳐지는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; data-alt=&quot;abc, def로 2번 송신&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QafE2/btrnHSLtJDC/dI1ywAKvepq4800jru0BaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQafE2%2FbtrnHSLtJDC%2FdI1ywAKvepq4800jru0BaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;654&quot; height=&quot;136&quot; data-origin-width=&quot;654&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;abc, def로 2번 송신&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; data-alt=&quot;abcdef 수신&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnI9vx/btrnB8hXfjy/aIsjkMZSHB6Mx6bKkuzbI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnI9vx%2FbtrnB8hXfjy%2FaIsjkMZSHB6Mx6bKkuzbI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;144&quot; data-origin-width=&quot;658&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;abcdef 수신&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림은 패킷 분리와 반대의 경우로 합쳐지는 경우입니다. 상대측에서 첫번째로 abc를 송신하고 두번째로 def를 송신하였을 때 수신하는 경우에는 abcdef가 한번에 들어오는 경우입니다. 위에서 설명드린 것과 같이 TCP 관련 Layor를 통해서 abc, def 패킷이 합쳐진 후 송신되어 1개의 패킷을 수신하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시와 같이 여러가지 경우로 패킷이 분리되거나 합쳐질 수 있습니다. TCP/IP 통신 시에 데이터의 형태나 크기가 다른 여러 메시지를 송수신 하기 때문에 이를 고려하여 패킷 수신 로직을 구현 해주셔야 합니다. 구현에 있어서 정답은 없고 사람 및 회사에 따라서 방식에 차이가 있을 것으로 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 앞부분에 헤더를 붙여서 통신하는 방식을 설명드리겠습니다. 헤더는 메시지 ID, 송수신 장비 번호, 메시지 크기 등과 같은 내용을 포함하게 됩니다. 패킷의 유효성 검사를 위해서 START/END CODE 및 CHECK SUM/CRC와 같은 항목을 추가하셔도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드로 자세히 설명드리겠습니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;위에서 설명되는 경우에 대한 처리는 main.c 코드의 ThreadParsing 부분에서 진행함으로 이 부분을 집중적으로 보시는 것을 추천드립니다. &lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;TCP/IP 통신 및 데이터 큐 코드는 중요도가 낮으므로 해당 로직에 대한 설명과 테스트 결과에 대한 설명 뒷부분에 게시하였습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio 속성 &amp;gt; 전처리기에서 _WINSOCK_DEPRECATED_NO_WARNINGS를 추가하셔야 에러없이 동작됨을 참고하시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;main.c 코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1639494571464&quot; class=&quot;c++ arduino&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;
#include &amp;lt;WinSock2.h&amp;gt;

#include &quot;dataQueue.h&quot;
#include &quot;tcpIpComm.h&quot;

#include &amp;lt;windows.h&amp;gt;

#pragma pack(push, 1)
typedef struct {
    uint32_t msgId;
    uint32_t srcId;
    uint32_t dstId;
    size_t msgSize;
}ST_MsgHeader;

typedef struct {
    ST_MsgHeader msgHeader;
    int8_t data[10];
}ST_TestPacket;
#pragma pack(pop) 

typedef enum {
    CONNECT,
    RECV,
    SEND
}CommStat;

typedef enum {
    WAIT_HEADER_RECV,
    GET_HEADER,
    WAIT_DATA_RECV,
    GET_DATA,
    MSG_SEND
}ParsingStat;

ST_Queue g_queue;

DWORD WINAPI ThreadReceive(void * arg)
{
    SOCKET clntSocket;

    CommStat stat = CONNECT;
    while (TRUE) {
        switch (stat) {
            case CONNECT:
                if (ClntConnection(5000, &amp;amp;clntSocket, SERV_IP_ADDR) == FALSE) {
                    Sleep(1000);
                }
                else {
                    stat = RECV;
                }
                break;
            case RECV:
                if (ClntRecv(&amp;amp;clntSocket, &amp;amp;g_queue) == FALSE) {
                    stat = CONNECT;
                }
                break;
        }

        Sleep(0);
    }    
}

DWORD WINAPI ThreadParsing(void* arg)
{
    int32_t i;
    int8_t * msg = NULL;
    ST_MsgHeader msgHeader;
    ParsingStat stat = WAIT_HEADER_RECV;

    while (TRUE) {
        switch (stat) {
        case WAIT_HEADER_RECV:
            if (QueueSize(&amp;amp;g_queue) &amp;gt;= sizeof(ST_MsgHeader)) {
                stat = GET_HEADER;
            }
            break;
        case GET_HEADER:
            QueueAddrPop(&amp;amp;g_queue, (int8_t*)&amp;amp;msgHeader, sizeof(ST_MsgHeader));
            stat = WAIT_DATA_RECV;
            break;
        case WAIT_DATA_RECV:
            if (QueueSize(&amp;amp;g_queue) &amp;gt;= (msgHeader.msgSize - sizeof(ST_MsgHeader))) {
                stat = GET_DATA;
            }
            break;
        case GET_DATA:
            msg = (int8_t *)malloc(msgHeader.msgSize);
            memcpy(msg, &amp;amp;msgHeader, sizeof(ST_MsgHeader));
            QueueAddrPop(&amp;amp;g_queue, &amp;amp;msg[sizeof(ST_MsgHeader)], (msgHeader.msgSize - sizeof(ST_MsgHeader)));
            stat = MSG_SEND;
            break;

        case MSG_SEND:
            printf(&quot;msgId=%d, srcId=%d, dstId=%d, msgSize=%d\n&quot;, msgHeader.msgId, msgHeader.srcId, msgHeader.dstId, msgHeader.msgSize);
            for (i = 0; i &amp;lt; (msgHeader.msgSize - sizeof(ST_MsgHeader)); i++) {
                printf(&quot;%d,&quot;, msg[sizeof(ST_MsgHeader) + i]);
            }
            printf(&quot;\n&quot;);
            switch (msgHeader.msgId) {
                // msgId 별 처리 ex) 다른 쓰레드로 전달
            }
            free(msg);
            stat = WAIT_HEADER_RECV;
            break;
        }

        Sleep(0);
    }
}

DWORD WINAPI ThreadSend(void* arg)
{
    int32_t i, j;
    SOCKET servSocket, clntSocket;
    ST_TestPacket packet[3];

    for (j = 0; j &amp;lt; 3; j++) {
    
        packet[j].msgHeader.msgId = j+1;
        packet[j].msgHeader.srcId = 1;
        packet[j].msgHeader.dstId = 2;
        packet[j].msgHeader.msgSize = sizeof(ST_TestPacket);

        for (i = 0; i &amp;lt; 10; i++) {
            packet[j].data[i] = j+1;
        }
    }

    CommStat stat = CONNECT;
    while (TRUE) {
        switch (stat) {
        case CONNECT:
            if (ServConnection(5000, &amp;amp;servSocket , &amp;amp;clntSocket) == FALSE) {
                Sleep(1000);
            }
            else {
                stat = SEND;
            }
            break;
        case SEND:
            // case 1 분할
            send(clntSocket, &amp;amp;packet[0], sizeof(ST_MsgHeader) + 5, 0);
            send(clntSocket, ((int8_t *)&amp;amp;packet[0] + sizeof(ST_MsgHeader) + 5), 5, 0);

            // case 2 합
            send(clntSocket, &amp;amp;packet[1], sizeof(ST_TestPacket) * 2, 0);
            Sleep(10000);
            break;
        }

        Sleep(0);
    }
}


int main()
{
    if (QueueInit(&amp;amp;g_queue, QUEUE_LENGTH) == NO) {
        printf(&quot;queue init fail\n&quot;);
    }

    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &amp;amp;wsaData);

    HANDLE hReceiveThrd, hParsingThrd, hSendThrd;
    DWORD threadId, threadParam;
    hReceiveThrd = CreateThread(NULL, 0, ThreadReceive, &amp;amp;threadParam, 0, &amp;amp;threadId);
    hParsingThrd = CreateThread(NULL, 0, ThreadParsing, &amp;amp;threadParam, 0, &amp;amp;threadId);
    hSendThrd = CreateThread(NULL, 0, ThreadSend, &amp;amp;threadParam, 0, &amp;amp;threadId);

    WaitForSingleObject(hReceiveThrd, INFINITE);
    WaitForSingleObject(hParsingThrd, INFINITE);
    WaitForSingleObject(hSendThrd, INFINITE);

    CloseHandle(hReceiveThrd);
    CloseHandle(hParsingThrd);
    CloseHandle(hSendThrd);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ThreadSend의 경우 테스트를 위한 쓰레드이고 ThreadReceive는 수신을 위한 쓰레드입니다. ThreadParsing이 분리, 합쳐진 패킷을 기존 패킷으로 파싱하는 쓰레드입니다. ThreadSend의 첫번째 케이스에서는 패킷이 분할되는 상황, 두번째 케이스에서는 패킷이 합쳐지는 상황에 대해서 모의하였습니다. ThreadReceive에서는 TCP/IP 수신 후 데이터를 큐에 Push합니다. ThreadParsing에서는 큐를 확인하고 Pop하여 파싱으로 기존 전송 패킷을 수신한 후 처리합니다. 아래의 그림은ThreadParsing에서 패킷을 수신하기 위한 파싱 로직입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NIbYO/btrnV6wpiQy/UiDwjhDBDkcCVFFKlKZya0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NIbYO/btrnV6wpiQy/UiDwjhDBDkcCVFFKlKZya0/img.png&quot; data-alt=&quot;패킷 수신 파싱 로직&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NIbYO/btrnV6wpiQy/UiDwjhDBDkcCVFFKlKZya0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNIbYO%2FbtrnV6wpiQy%2FUiDwjhDBDkcCVFFKlKZya0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;813&quot; height=&quot;216&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;패킷 수신 파싱 로직&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 결과는 아래의 그림과 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5vT5w/btrnW30q3VC/yLZ5lusNG7HK2oEyPFnKKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5vT5w/btrnW30q3VC/yLZ5lusNG7HK2oEyPFnKKK/img.png&quot; data-alt=&quot;테스트 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5vT5w/btrnW30q3VC/yLZ5lusNG7HK2oEyPFnKKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5vT5w%2FbtrnW30q3VC%2FyLZ5lusNG7HK2oEyPFnKKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;373&quot; height=&quot;129&quot; data-origin-width=&quot;373&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;테스트 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TCP/IP 통신 코드 헤더&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1639493974180&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#pragma once

#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;WinSock2.h&amp;gt;
#include &quot;dataQueue.h&quot;

#define RECV_BUFFER_SIZE (16384)
#define SERV_IP_ADDR (&quot;127.0.0.1&quot;)

int32_t ServConnection(int16_t port, SOCKET* servSocket, SOCKET* clntSocket);
int32_t ServRecv(SOCKET* servSocket, SOCKET* clntSocket, ST_Queue* queue);
int32_t ClntConnection(int16_t port, SOCKET* clntSocket, char* ipAddr);
int32_t ClntRecv(SOCKET* socket, ST_Queue* queue);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TCP/IP 통신 코드&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1639493997707&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;tcpIpComm.h&quot;

int32_t ServConnection(int16_t port, SOCKET* servSocket, SOCKET* clntSocket)
{
	int32_t result = FALSE;
	int32_t option = 1;
	SOCKADDR_IN servAddr, clntAddr;
	int32_t szClntAddr;

	do {
		*servSocket = socket(PF_INET, SOCK_STREAM, 0);

		if (*servSocket == INVALID_SOCKET) {
			break;
		}

		memset(&amp;amp;servAddr, 0, sizeof(servAddr));

		servAddr.sin_family = AF_INET;
		servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
		servAddr.sin_port = htons(port);

		if (bind(*servSocket, (SOCKADDR*)&amp;amp;servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
			closesocket(*servSocket);
			break;
		}

		if (listen(*servSocket, 5) == SOCKET_ERROR) {
			closesocket(*servSocket);
			break;
		}

		szClntAddr = sizeof(clntAddr);
		*clntSocket = accept(*servSocket, (SOCKADDR*)&amp;amp;clntAddr, &amp;amp;szClntAddr);   // 클라이언트와 통신 할

		if (*clntSocket == INVALID_SOCKET) {
			closesocket(*clntSocket);
			closesocket(*servSocket);
			break;
		}
		else {
			result = TRUE;
			break;
		}
	} while (0);
	
	return result;
}

int32_t ServRecv(SOCKET* servSocket, SOCKET* clntSocket, ST_Queue* queue)
{
	int32_t result, len;
	static int8_t recvBuf[RECV_BUFFER_SIZE];

	len = recv(*clntSocket, recvBuf, RECV_BUFFER_SIZE, 0);

	if (len &amp;lt;= 0) {
		closesocket(*servSocket);
		closesocket(*clntSocket);
		result = FALSE;
	}
	else {
		QueueAddrPush(queue, recvBuf, len);
		result = TRUE;
	}

	return result;
}

int32_t ClntConnection(int16_t port, SOCKET* clntSocket, char * ipAddr)
{
	int32_t result = FALSE;

	SOCKADDR_IN servAddr;

	do {
		*clntSocket = socket(PF_INET, SOCK_STREAM, 0);

		if (*clntSocket == INVALID_SOCKET) {
			break;
		}

		servAddr.sin_family = AF_INET;
		servAddr.sin_addr.s_addr = inet_addr(ipAddr);
		servAddr.sin_port = htons(port);
		
		if (connect(*clntSocket, (SOCKADDR*)&amp;amp;servAddr, sizeof(servAddr)) == SOCKET_ERROR) {
			closesocket(*clntSocket);
			break;
		}
		else {
			result = TRUE;
			break;
		}

	} while (0);

	return result;
}

int32_t ClntRecv(SOCKET* socket, ST_Queue* queue)
{
	int32_t result, len;
	static int8_t recvBuf[RECV_BUFFER_SIZE];

	len = recv(*socket, recvBuf, RECV_BUFFER_SIZE, 0);

	if (len &amp;lt;= 0) {
		closesocket(*socket);
		result = FALSE;
	}
	else {
		QueueAddrPush(queue, recvBuf, len);
		result = TRUE;
	}

	return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;데이터 큐 코드 헤더&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1639494049595&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#pragma once

#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

#define NO (0)
#define YES (!NO)

#define QUEUE_LENGTH (65536)

typedef struct {
    int32_t front;
    int32_t back;
    int32_t size;
    int32_t bufSize;
    int8_t* buf;

    CRITICAL_SECTION lock;
}ST_Queue;

int32_t IsQueueEmpty(ST_Queue* queue);
int32_t QueueSize(ST_Queue* queue);
int32_t IsQueueFull(ST_Queue* queue);
int32_t QueueInit(ST_Queue* queue, int32_t queueLength);
void QueueDelete(ST_Queue* queue);
void QueuePush(ST_Queue* queue, int8_t data);
void QueueAddrPush(ST_Queue* queue, int8_t* data, size_t dataSize);
int32_t QueuePop(ST_Queue* queue);
void QueueAddrPop(ST_Queue* queue, int8_t* data, size_t dataSize);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;데이터 큐 코드&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1639494150739&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &quot;dataQueue.h&quot;

int32_t IsQueueEmpty(ST_Queue* queue)
{
    int32_t result;

    EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
    if (queue-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }
    LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);

    return result;
}

int32_t QueueSize(ST_Queue* queue)
{
    int32_t result;

    EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
    result = queue-&amp;gt;size;
    LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);

    return result;
}

int32_t IsQueueFull(ST_Queue* queue)
{
    int32_t result;

    EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
    if (queue-&amp;gt;size == queue-&amp;gt;bufSize) {
        result = YES;
    }
    else {
        result = NO;
    }
    LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);

    return result;
}

int32_t QueueInit(ST_Queue* queue, int32_t queueLength)
{
    int32_t result;

    queue-&amp;gt;buf = (int8_t*)malloc(sizeof(int8_t) * queueLength);

    if (queue-&amp;gt;buf != NULL) {
        queue-&amp;gt;front = 0;
        queue-&amp;gt;back = 0;
        queue-&amp;gt;size = 0;
        queue-&amp;gt;bufSize = queueLength;
        memset(queue-&amp;gt;buf, 0, (sizeof(int8_t) * queueLength));
        InitializeCriticalSection(&amp;amp;queue-&amp;gt;lock);

        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

void QueueDelete(ST_Queue* queue)
{
    free(queue-&amp;gt;buf);
    DeleteCriticalSection(&amp;amp;queue-&amp;gt;lock);
}

void QueuePush(ST_Queue* queue, int8_t data)
{
    if (IsQueueFull(queue) == YES) {
        printf(&quot;queue is full\n&quot;);
    }
    else {
        EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
        queue-&amp;gt;buf[queue-&amp;gt;back] = data;
        queue-&amp;gt;back++;
        queue-&amp;gt;size++;

        if (queue-&amp;gt;back == queue-&amp;gt;bufSize) {
            queue-&amp;gt;back = 0;
        }
        LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);
    }
}

void QueueAddrPush(ST_Queue* queue, int8_t* data, size_t dataSize)
{
    int32_t i;
    if (IsQueueFull(queue) == YES) {
        printf(&quot;queue is full\n&quot;);
    }
    else {
        EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
        for (i = 0; i &amp;lt; dataSize; i++) {
            queue-&amp;gt;buf[queue-&amp;gt;back] = data[i];
            queue-&amp;gt;back++;
            queue-&amp;gt;size++;

            if (queue-&amp;gt;back == queue-&amp;gt;bufSize) {
                queue-&amp;gt;back = 0;
            }
        }
        LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);
    }
}

int32_t QueuePop(ST_Queue* queue)
{
    int8_t result = 0;

    if (IsQueueEmpty(queue) == YES) {
        printf(&quot;queue is emtpy\n&quot;);
    }
    else {
        EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
        result = queue-&amp;gt;buf[queue-&amp;gt;front];
        queue-&amp;gt;front++;
        queue-&amp;gt;size--;

        if (queue-&amp;gt;front == queue-&amp;gt;bufSize) {
            queue-&amp;gt;front = 0;
        }
        LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);
    }

    return result;
}

void QueueAddrPop(ST_Queue* queue, int8_t* data, size_t dataSize)
{
    int32_t i;
    if (IsQueueEmpty(queue) == YES) {
        printf(&quot;queue is emtpy\n&quot;);
    }
    else {
        EnterCriticalSection(&amp;amp;queue-&amp;gt;lock);
        for (i = 0; i &amp;lt; dataSize; i++) {
            data[i] = queue-&amp;gt;buf[queue-&amp;gt;front];
            queue-&amp;gt;front++;
            queue-&amp;gt;size--;

            if (queue-&amp;gt;front == queue-&amp;gt;bufSize) {
                queue-&amp;gt;front = 0;
            }
        }
        LeaveCriticalSection(&amp;amp;queue-&amp;gt;lock);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상으로 패킷 분리 및 합침을 고려한 TCP/IP 통신 수신 로직에 대한 설명을 마치겠습니다!&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C/C++</category>
      <category>TCP/IP</category>
      <category>패킷 분리</category>
      <category>패킷 분할</category>
      <category>패킷 합침</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/22</guid>
      <comments>https://elevate-yourself.tistory.com/22#entry22comment</comments>
      <pubDate>Wed, 15 Dec 2021 00:37:21 +0900</pubDate>
    </item>
    <item>
      <title>[c/c++] 프로세스 우선순위 변경</title>
      <link>https://elevate-yourself.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 운영체제는 리얼타임 OS가 아니기때문에 윈도우 환경에서 실행되는 프로세스의 경우 실시간으로 동작되는 것은 어렵습니다. 실시간이 중요한 경우 OS를 윈도우를 사용하지 않고 상대적으로 백그라운드에서 동작되는 프로세스가 적은 리눅스를 사용하거나 VxWorks와 같은 RTOS 종류의 운영체제를 사용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 윈도우 환경에서 프로세스를 최대한 실시간으로 운영하기 위한 방법에서 단순한 방법 중 하나인 프로세스 우선순위를 변경하는 방법에 대해서 설명드리겠습니다. 반대의 경우로 우선순위를 낮게 변경하는 경우에도 적용할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CgrHb/btrnv1P1qRw/GjVkMx5KKACQCcHpAoAvRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CgrHb/btrnv1P1qRw/GjVkMx5KKACQCcHpAoAvRk/img.png&quot; data-alt=&quot;윈도우 프로그램 기본 우선순위&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CgrHb/btrnv1P1qRw/GjVkMx5KKACQCcHpAoAvRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCgrHb%2Fbtrnv1P1qRw%2FGjVkMx5KKACQCcHpAoAvRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;666&quot; height=&quot;595&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우 프로그램 기본 우선순위&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio를 통해서 생성된 프로그램을 실행하였을 때 기본적인 우선순위는 보통입니다. 작업 관리자의 세부 정보에서 해당하는 프로그램의 우선순위 설정에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스 우선순위 변경에는 2가지 방법이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;첫 번째 방법은 작업 관리자를 이용한 방법&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TP61C/btrnyI90pqW/8FtkurbTCmb9Z2EC8BjpQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TP61C/btrnyI90pqW/8FtkurbTCmb9Z2EC8BjpQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TP61C/btrnyI90pqW/8FtkurbTCmb9Z2EC8BjpQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTP61C%2FbtrnyI90pqW%2F8FtkurbTCmb9Z2EC8BjpQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;666&quot; height=&quot;592&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림과 같이 해당하는 프로그램의 우선순위를 우선순위 설정에서 선택하여 변경할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 적용할 수 있지만 프로그램을 매번 실행할 때마다 프로세스 우선순위를 변경해야 하기 때문에 불편하여 현실적으로 사용 불가한 것으로 판단됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 번째 방법은 Visual Studio에서 우선순위 변경 코드 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1639064388754&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;windows.h&amp;gt;

int main()
{
	SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

	int32_t i = 0; 
	while (1) {
		printf(&quot;%d\n&quot;,i);
		Sleep(1000);
		i++;
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;windows 헤더 파일을 선언하고 SetPriorityClass 함수를 사용하여 프로세스 우선순위를 변경할 수 있습니다. 첫 번째 인자에는 GetCurrentProcess함수를 수행하여 현재 프로세스를 입력하고, 두 번째 인자에 변경하고자 하는 우선순위를 입력하면 됩니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 140px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;우선순위&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;PriorityClass&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;실시간(R)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;REALTIME_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;높음(H)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;HIGH_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;높은 우선 순위(A)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;ABOVE_NORMAL_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;보통(N)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;NORMAL_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;낮은 우선 순위(B)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;BELOW_NORMAL_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;낮음(L)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;IDLE_PRIORITY_CLASS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실시간(R) 설정을 위해서 REALTIME_PRIORITY_CLASS를 적용하는 경우 작업 관리자에서 확인하였을 때 프로세스 우선순위는 실시간(R)이 아닌 높음(H)로 설정됨을 확인하실 수 있습니다. Visual Studio의 프로젝트 속성에서 UAC 실행 수준을 requireAdministrator로 변경해야 실시간(R) 설정이 정상적으로 가능합니다. 아래의 그림 순서대로 적용하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;829&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bojy9G/btrnxmsBz6Q/5UfUMg7CIjYM22O3dVJ2kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bojy9G/btrnxmsBz6Q/5UfUMg7CIjYM22O3dVJ2kK/img.png&quot; data-alt=&quot;1. 프로젝트 속성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bojy9G/btrnxmsBz6Q/5UfUMg7CIjYM22O3dVJ2kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbojy9G%2FbtrnxmsBz6Q%2F5UfUMg7CIjYM22O3dVJ2kK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;397&quot; height=&quot;662&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;829&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1. 프로젝트 속성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnPaay/btrnuXHCuSW/WloLEQoCHJKpX7EtZbypKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnPaay/btrnuXHCuSW/WloLEQoCHJKpX7EtZbypKK/img.png&quot; data-alt=&quot;2. 링커 &amp;amp;gt; 매니페스트 파일 &amp;amp;gt; UAC 실행 수준&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnPaay/btrnuXHCuSW/WloLEQoCHJKpX7EtZbypKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnPaay%2FbtrnuXHCuSW%2FWloLEQoCHJKpX7EtZbypKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;786&quot; height=&quot;544&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2. 링커 &amp;gt; 매니페스트 파일 &amp;gt; UAC 실행 수준&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우 최근 구현한 윈도우 프로그램에서 우선순위를 실시간으로 변경하여 간헐적으로 발생한 이더넷 통신 송수신 지연 문제(송수신 함수 수행 전 타 프로세스 연산 수행)를 해결한 경험이 있습니다. 이러한 경우와 같이 윈도우 환경에서 프로세스의 연산을 보다 빠르게 처리하고 싶은 분들에게 추천합니다. 그러나 타 프로세스에 영향에 있을 수 있으니 이 부분은 주의하셔서 적용하시면 될 것 같습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C/C++</category>
      <category>Visual Studio</category>
      <category>windows</category>
      <category>윈도우</category>
      <category>프로세스</category>
      <category>프로세스 우선순위</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/21</guid>
      <comments>https://elevate-yourself.tistory.com/21#entry21comment</comments>
      <pubDate>Fri, 10 Dec 2021 01:04:17 +0900</pubDate>
    </item>
    <item>
      <title>[c언어/c++] 분기문(switch) 제거</title>
      <link>https://elevate-yourself.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서는 분기문(switch)를 제거하는 방법에 대해서 설명해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;분기문에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분기문은 조건에 따라서 각각 다른 코드를 실행하도록 합니다. if문, switch문이 조건에 따라서 실행되는 코드가 달라지기 때문에 분기문이라고 생각하시면 됩니다. 이러한 분기문은 코드 작성 시 필수적으로 사용해야하는 문법입니다. 그러나 분기 조건이 많아질수록 코드를 이해하기 어려워지므로 가독성이 떨어지게 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;분기문 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1609489617246&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main()
{
    int32_t data, result;

    result = 0;
    data = rand() % 4;

    switch (data) {
        case 0:
            result = data * 2;
            break;
        case 1:
            result = data * 3;
            break;
        case 2:
            result = data * 4;
            break;
        case 3:
            result = data * 5;
            break;
        default:
            break;
    }

    printf(&quot;data = %d, result = %d\n&quot;, data, result);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;분기문 제거 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 분기문에 대한 설명과 같이 분기 조건이 많아질수록 코드가 복잡해져서 이해가 힘들어져서 코드의 가독성이 떨어지게됩니다. &lt;span style=&quot;color: #333333;&quot;&gt;분기문의 조건이 많아 복잡한 경우 분기문을 제거하여 &lt;/span&gt;코드 가독성을 증가시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;분기문 제거 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1611157368424&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main()
{
    int32_t data, result;

    result = 0;
    data = rand() % 4;

    int32_t table[] = { data * 2, data * 3, data * 4, data * 5 };

    result = table[data];

    printf(&quot;data = %d, result = %d\n&quot;, data, result);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 예시로 보여드린 분기문 코드를 참조테이블을 사용하여 제거한 코드입니다. 코드가 간결해졌으며, 분기 조건이 추가되는경우에도 table배열에 추가하고자 하는 로직을 넣어 쉽게 추가할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시에서는 분기 조건에 따라서 result함수의 값이 달라지게됩니다. 이와 다르게 분기 조건에 따라서 실행되는함수가 달리지게 되는 경우에는 함수포인터를 사용하여 분기문을 제거할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;분기조건에 따라 실행되는 함수가 달라지는 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1611158160279&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

void FunctionA(void)
{
    printf(&quot;A\n&quot;);
}

void FunctionB(void)
{
    printf(&quot;B\n&quot;);
}

void FunctionC(void)
{
    printf(&quot;C\n&quot;);
}

void FunctionD(void)
{
    printf(&quot;D\n&quot;);
}

int main()
{
    int32_t data;
    data = rand() % 4;

    switch (data) {
        case 0:
            FunctionA();
            break;
        case 1:
            FunctionB();
            break;
        case 2:
            FunctionC();
            break;
        case 3:
            FunctionD();
            break;
        default:
            break;
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;함수포인터를 이용한 분기문 제거 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1611158063993&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

void FunctionA(void)
{
    printf(&quot;A\n&quot;);
}

void FunctionB(void)
{
    printf(&quot;B\n&quot;);
}

void FunctionC(void)
{
    printf(&quot;C\n&quot;);
}

void FunctionD(void)
{
    printf(&quot;D\n&quot;);
}

int main()
{
    int32_t data;
    data = rand() % 4;

    void(*pFunc[])(void) = {FunctionA, FunctionB, FunctionC, FunctionD};
    
    pFunc[data]();

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통신으로 데이터를 수신하는 경우에 메시지에 따라서 실행되는 함수가 달라지게 되는데 이러한 경우에 &lt;b&gt;&quot;함수포인터를 이용하여 분기를 제거하는 코드&quot;&lt;/b&gt;를 유용하게 사용할 수 있습니다. 메시지의 개수가 많기 때문에 코드가 복잡해지며 메시지가 추가되는 경우에 메시지에 해당하는 처리 함수를 구현하고 함수포인터에 추가만 해주면 되기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 분기문 제거에 대한 설명을 마치도록 하겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C언어</category>
      <category>분기문제거</category>
      <category>코드최적화</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/20</guid>
      <comments>https://elevate-yourself.tistory.com/20#entry20comment</comments>
      <pubDate>Thu, 21 Jan 2021 01:03:06 +0900</pubDate>
    </item>
    <item>
      <title>[c언어] 스택(Stack)</title>
      <link>https://elevate-yourself.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다! 이번 포스팅에서는 스택에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;스택에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;스택은 입력된 데이터들을 저장하고 저장된 순서와 반대로 데이터를 출력하는 자료구조입니다. 큐의 가장 큰 특징은 먼저 들어온 데이터는 가장 마지막에 나가는 것입니다. 이것을&lt;span&gt;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;후&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;입선출 또는 LIFO&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이라고 주로 표현합니다. 쉽게 예를 들어서 접시 쌓기를 생각하시면 될 것 같습니다. 가장 먼저 정리한 접시가 가장 아래에 쌓여있고 가장 최근에 정리한 접시가 가장 위에 쌓여있기 때문에 가장 최근 쌓은 접시를 가장 먼저 사용하게 되는 것과 같이 데이터가 관리되게 됩니다. 스택 또한 큐와 동일하게 배열과 링크드리스트를 사용하여 구현할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;스택 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택은 dfs(depth first search)와 같은 알고리즘에서 사용되며 후입선출을 해야하는 상황에서 유용하게 사용하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적인 예로 redo, undo가 있을 것입니다. 파워포인트에서 ctrl+z를 누르게 되면 현재 작성된 상황에서 이전 상황으로 돌아가게 됩니다. 이러한 상황을 구현할 때 스택을 유용하게 사용할 수 있습니다. 스택에 작성 데이터들을 순차적으로 입력해놓으면 ctrl+z를 누를때마다 스택에서 이전에 작성된 상황(가장 최근에 입력된 작성 데이터)을 쉽게 불러올 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 이름에서부터 느껴지듯이 스택메모리에서도 사용됩니다. a, b라는 함수가 있고 a함수에서 b함수를 호출한다고 가정해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1610489635811&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

void FunctionB()
{
    int32_t data[] = { 3, 4 };

    printf(&quot;FunctionB data1=%d, data2=%d, dataSum=%d\n&quot;, data[0], data[1], data[0] + data[1]);
}

void FunctionA()
{
    int32_t data[] = { 1, 2 };

    FunctionB();

    printf(&quot;FunctionA data1=%d, data2=%d, dataSum=%d\n&quot;, data[0], data[1], data[0] + data[1]);
}

int main()
{
    FunctionA();

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FunctionA 호출 시 순서&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SYttP/btqTrTnvVbf/0WoKk4WGjzqZJgP4eiPIYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SYttP/btqTrTnvVbf/0WoKk4WGjzqZJgP4eiPIYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SYttP/btqTrTnvVbf/0WoKk4WGjzqZJgP4eiPIYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSYttP%2FbtqTrTnvVbf%2F0WoKk4WGjzqZJgP4eiPIYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. FunctionA 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. FunctionA의 data배열 스택에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. FunctionA의 현재주소(복귀주소) 스택에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4. FucntionB 호출&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. FunctionB의 data배열 스택에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. FunctionB printf문 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. FunctionB의 data배열 스택에서 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. FunctionA의 복귀주소 스택에서 읽기 및 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;9. FunctionA의 복귀주소로 복귀&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10. FunctionA printf문 실행&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11. Functionㅁ data배열 스택에서 삭제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시는 쉽게 설명하기 위한 예시이며 실제 함수가 분기될 때에는 추가적인 절차가 있음을 참고바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배열을 이용한 스택 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1610496185415&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;typedef struct {
    int32_t* buf;
    uint32_t back;
    size_t size;
    size_t bufSize;
}ST_Stack;

int32_t StackInit(ST_Stack* stack, size_t stackSize)
{
    int32_t result;

    stack-&amp;gt;buf = (int32_t*)malloc(sizeof(int32_t) * stackSize);

    if (stack-&amp;gt;buf == NULL) {
        result = NO;
    }
    else {
        stack-&amp;gt;back = 0;
        stack-&amp;gt;size = 0;
        stack-&amp;gt;bufSize = stackSize;

        result = YES;
    }
    
    return result;
}

void StackDelete(ST_Stack* stack)
{
    free(stack-&amp;gt;buf);
    stack-&amp;gt;back = 0;
    stack-&amp;gt;size = 0;
    stack-&amp;gt;bufSize = 0;
}

int32_t IsStackEmpty(ST_Stack* stack)
{
    int32_t result;

    if (stack-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }
    
    return result;
}

int32_t IsStackFull(ST_Stack* stack)
{
    int32_t result;

    if (stack-&amp;gt;size == stack-&amp;gt;bufSize) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

void StackPush(ST_Stack* stack, int32_t data)
{
    if (IsStackFull(stack) == YES) {
        printf(&quot;stack is full\n&quot;);
    }
    else {
        stack-&amp;gt;buf[stack-&amp;gt;back] = data;
        stack-&amp;gt;back++;
        stack-&amp;gt;size++;
    }
}

int32_t StackPop(ST_Stack* stack)
{
    int32_t result = 0;

    if (IsStackEmpty(stack) == YES) {
        printf(&quot;stack is empty\n&quot;);
    }
    else {
        stack-&amp;gt;back--;
        result = stack-&amp;gt;buf[stack-&amp;gt;back];
        stack-&amp;gt;size--;
    }

    return result;
}

void StackPrint(ST_Stack* stack)
{
    int32_t i;

    for (i = 0; i &amp;lt; stack-&amp;gt;size; i++) {
        printf(&quot;i=%d, %d\n&quot;, i, stack-&amp;gt;buf[i]);
    }
}

int main()
{
    #define STACK_SIZE (8)
    #define POP_SIZE (4)

    ST_Stack stack;
    int32_t i;
    int32_t popData[POP_SIZE];

    StackInit(&amp;amp;stack, STACK_SIZE);

    StackPop(&amp;amp;stack);

    for (i = 0; i &amp;lt; STACK_SIZE; i++) {
        StackPush(&amp;amp;stack, i);
    }
    StackPush(&amp;amp;stack, 8);

    StackPrint(&amp;amp;stack);
    
    for (i = 0; i &amp;lt; POP_SIZE; i++) {
        popData[i] =  StackPop(&amp;amp;stack);
        printf(&quot;pop=%d\n&quot;, popData[i]);
    }

    StackPrint(&amp;amp;stack);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;링크드리스트를 이용한 스택 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1610496102184&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

typedef struct ST_Node {
    int32_t data;
    struct ST_Node* next;
    struct ST_Node* prev;
}ST_Node;

typedef struct {
    ST_Node* front;
    ST_Node* back;
    int32_t size;
}ST_Stack;

int32_t IsStackEmpty(ST_Stack* stack)
{
    int32_t result;

    if (stack-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

int32_t StackInit(ST_Stack* stack)
{
    int32_t result = YES;

    stack-&amp;gt;front = NULL;
    stack-&amp;gt;back = NULL;
    stack-&amp;gt;size = 0;

    return result;
}

void StackDelete(ST_Stack* stack)
{
    int32_t i;
    ST_Node* temp;

    for (i = 0; i &amp;lt; stack-&amp;gt;size; i++) {
        temp = stack-&amp;gt;front;
        stack-&amp;gt;front = stack-&amp;gt;front-&amp;gt;next;
        free(temp);
    }

    stack-&amp;gt;front = NULL;
    stack-&amp;gt;back = NULL;
    stack-&amp;gt;size = 0;
}

void StackPush(ST_Stack* stack, int32_t data)
{
    ST_Node* addNode;

    addNode = (ST_Node*)malloc(sizeof(ST_Node));

    if (addNode == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        addNode-&amp;gt;data = data;
        addNode-&amp;gt;next = NULL;

        if (IsStackEmpty(stack) == YES) {
            addNode-&amp;gt;prev = NULL;
            stack-&amp;gt;front = addNode;
            stack-&amp;gt;back = addNode;
        }
        else {
            addNode-&amp;gt;prev = stack-&amp;gt;back;
            stack-&amp;gt;back-&amp;gt;next = addNode;
            stack-&amp;gt;back = addNode;
        }
        stack-&amp;gt;size++;
    }
}

int32_t StackPop(ST_Stack* stack)
{
    int32_t result = 0;
    ST_Node* del;

    if (IsStackEmpty(stack) == YES) {
        printf(&quot;stack is emtpy\n&quot;);
    }
    else {
        result = stack-&amp;gt;back-&amp;gt;data;
        del = stack-&amp;gt;back;
        stack-&amp;gt;back = stack-&amp;gt;back-&amp;gt;prev;
        stack-&amp;gt;size--;

        free(del);
    }

    return result;
}

void StackPrint(ST_Stack* stack)
{
    int32_t i;
    ST_Node* temp;

    temp = stack-&amp;gt;front;
    for (i = 0; i &amp;lt; stack-&amp;gt;size; i++) {
        printf(&quot;i=%d, %d\n&quot;, i, temp-&amp;gt;data);
        temp = temp-&amp;gt;next;
    }
}

int main()
{
#define POP_SIZE (4)

    ST_Stack stack;
    int32_t i;
    int32_t popData[POP_SIZE];

    StackInit(&amp;amp;stack);

    StackPop(&amp;amp;stack);

    StackPush(&amp;amp;stack, 0);
    StackPop(&amp;amp;stack);

    for (i = 0; i &amp;lt; STACK_SIZE; i++) {
        StackPush(&amp;amp;stack, i);
    }

    StackPrint(&amp;amp;stack);

    for (i = 0; i &amp;lt; POP_SIZE; i++) {
        popData[i] = StackPop(&amp;amp;stack);
        printf(&quot;pop=%d\n&quot;, popData[i]);
    }

    StackPrint(&amp;amp;stack);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 스택에 대한 설명을 마치도록 하겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C언어</category>
      <category>stack</category>
      <category>스택</category>
      <category>자료구조</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/19</guid>
      <comments>https://elevate-yourself.tistory.com/19#entry19comment</comments>
      <pubDate>Thu, 14 Jan 2021 07:54:24 +0900</pubDate>
    </item>
    <item>
      <title>[c언어] 링크드리스트(Linked List)</title>
      <link>https://elevate-yourself.tistory.com/18</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다! 이번 포스팅에서는 링크드리스트에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;링크드리스트에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 노드끼리 연결되어 자료를 관리하는 자료구조입니다. 포인터를 통해서 노드에서 다른노드를 가르킴으로써 노드끼리 연결할 수 있습니다. 그러므로 각 노드에는 노드를 가르킬 수 있는 포인터를 포함하고 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wSqgc/btqSdtbTvIO/WBRlrQqtEmrML6WF0qrJ7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wSqgc/btqSdtbTvIO/WBRlrQqtEmrML6WF0qrJ7k/img.png&quot; data-alt=&quot;링크드리스트 구조 예&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wSqgc/btqSdtbTvIO/WBRlrQqtEmrML6WF0qrJ7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwSqgc%2FbtqSdtbTvIO%2FWBRlrQqtEmrML6WF0qrJ7k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;링크드리스트 구조 예&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크드리스트를 이해하기 위해서는 포인터, 힙, 동적 메모리 할당에 대한 이해가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각에 대해서 간단하게 설명하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 포인터&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포인터란 메모리의 주소를 저장할 수 있는 변수입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvDOIb/btqSjA2AcPt/IGsyrqlyDDtSkQP6XOvGhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvDOIb/btqSjA2AcPt/IGsyrqlyDDtSkQP6XOvGhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvDOIb/btqSjA2AcPt/IGsyrqlyDDtSkQP6XOvGhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvDOIb%2FbtqSjA2AcPt%2FIGsyrqlyDDtSkQP6XOvGhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 선언 시 해당 변수는 메모리의 어떠한 영역에 위치하게 됩니다. 이 때 어떤 영역에 위치하는 지 표현 하는 것이 주소입니다. 각 변수는 유일한 주소를 가지게 됩니다. 포인터가 주소를 저장하는 것을 주소를 가르킨다라고 표현하기도 합니다. 그러므로 포인터는 가리키는 메모리의 주소를 통해서 해당 주소의 변수에 접근하여 값을 읽어오거나 수정할 수 있습니다. 링크드리스트에서는 노드 포인터를 통해서 연결하고자 하는 노드의 주소를 가르키게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 힙과 동적 메모리 할당&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z9AYq/btqR3Sw8NR8/OKA0ESSIf1n0jvHlTjnp21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z9AYq/btqR3Sw8NR8/OKA0ESSIf1n0jvHlTjnp21/img.png&quot; data-alt=&quot;변수 메모리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z9AYq/btqR3Sw8NR8/OKA0ESSIf1n0jvHlTjnp21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ9AYq%2FbtqR3Sw8NR8%2FOKA0ESSIf1n0jvHlTjnp21%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;변수 메모리&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙은 메모리영역 중 하나로 프로그램이 실행되며 필요한 만큼 할당하여 사용할 수 있는 메모리 영역을 말합니다. 힙 영역에서 사용 할 메모리를 할당받는 것을 동적 메모리 할당이라고 합니다. malloc을 통해서 동적 메모리 할당을 하며 할당받은 메모리를 해제하기 위해서는 free를 사용하게 됩니다. 동적 메모리 할당 후 할당된 메모리 영역을 미 사용 시에는 free를 통해서 무조건 해제 해야 한다는 점 주의바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램 실행 시에 사용 해야 할 메모리의 크기가 결정되는 상황에서 동적 메모리 할당이 필요하게 됩니다. 링크드리스트는 데이터가 입력될 때 노드를 힙 영역에 할당하고 삭제할 때 노드를 힙 영역에서 해제하게 됩니다. 그러므로 링크드리스트는 배열과 다르게 프로그램 실행 시에 크기가 변경될 수 있으며 힙 영역에서 사용할 공간이 있을 때 까지 크기를 증가시킬 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgUaGS/btqR9lMgj47/mOIwkrRpobYhK4dMjYsDV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgUaGS/btqR9lMgj47/mOIwkrRpobYhK4dMjYsDV0/img.png&quot; data-alt=&quot;메모리 측면에서 링크드리스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgUaGS/btqR9lMgj47/mOIwkrRpobYhK4dMjYsDV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgUaGS%2FbtqR9lMgj47%2FmOIwkrRpobYhK4dMjYsDV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;메모리 측면에서 링크드리스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;링크드리스트 종류&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크드리스트는 단일 연결 리스트(Singly Linked List)와 이중 연결 리스트(Doubly Linked List)로 나눌 수 있습니다. 이는 단방향 연결리스트, 양방향 연결리스트로도 표현되곤 합니다. 단일 연결 리스트는 노드가 1개의 노드를 가르키는 구조이지만 이중 연결 리스트는 노드가 2개의 노드를 가리키는 구조입니다. 단일 연결 리스트는 한방향으로 탐색할 수 있지만 이중 연결 리스트는 양방향으로 탐색할 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biBKys/btqR9lyEQ4i/akEWKCtd5ITKuIanfOiOS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biBKys/btqR9lyEQ4i/akEWKCtd5ITKuIanfOiOS1/img.png&quot; data-alt=&quot;단일 연결 리스트 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biBKys/btqR9lyEQ4i/akEWKCtd5ITKuIanfOiOS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiBKys%2FbtqR9lyEQ4i%2FakEWKCtd5ITKuIanfOiOS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;단일 연결 리스트 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KZdQR/btqSdtJHpZC/ktFQMkv7E1uAsbnWKzMAFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KZdQR/btqSdtJHpZC/ktFQMkv7E1uAsbnWKzMAFK/img.png&quot; data-alt=&quot;이중 연결 리스트 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KZdQR/btqSdtJHpZC/ktFQMkv7E1uAsbnWKzMAFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKZdQR%2FbtqSdtJHpZC%2FktFQMkv7E1uAsbnWKzMAFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이중 연결 리스트 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;링크드리스트 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크드리스트는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;데이터 삽입 및 삭제가 빈번하게 일어나는 경우&lt;/b&gt;&lt;/span&gt; 주로 사용할 수 있습니다. 어레이 리스트와 비교했을 때 어레이 리스트의 경우 중간 인덱스에 데이터를 삽입하거나 삭제해야하는 경우 삽입 및 삭제 후 데이터들을 1인덱스씩 이동 시켜 줘야 하기 때문에 연산시간이 오래 걸리게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크드리스트의 경우 데이터 삽입 시 노드를 추가하고 해당하는 위치에서 기존 노드들의 연결을 끊고 기존노드들과 새로운 노드에 연결하면됩니다. 데이터 삭제 시 이전 노드와 다음 노드를 연결하고 해당 노드를 해제하여 삭제하면 됩니다.그러나 탐색 시 이진 탐색(bineary search)과 같은 방법을 사용할 수 없고 순차적으로 진행해야하며 인덱스 참조가 불가능하고 순차적으로 노드를 이동해가며 데이터의 값을 읽어 와야 된다는 단점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단일 연결리스트 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1610265537854&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

typedef struct ST_Node {
    int32_t data;
    struct ST_Node* next;
}ST_Node;

typedef struct ST_LinkedList {
    int32_t size;
    ST_Node* front;
    ST_Node* back;
}ST_LinkedList;

void LinkedListInit(ST_LinkedList * linkedList)
{
    linkedList-&amp;gt;size = 0;
    linkedList-&amp;gt;front = NULL;
    linkedList-&amp;gt;back = NULL;
}

void LinkedListDelete(ST_LinkedList* linkedList)
{
    int32_t i;
    ST_Node* del;

    for(i = 0; i &amp;lt; linkedList-&amp;gt;size; i++){
        del = linkedList-&amp;gt;front;
        linkedList-&amp;gt;front = linkedList-&amp;gt;front-&amp;gt;next;
        free(del);
    }

    LinkedListInit(linkedList);
}

int32_t IsLinkedListEmpty(ST_LinkedList* linkedList)
{
    int32_t result;

    if (linkedList-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

void LinkedListFrontPush(ST_LinkedList* linkedList, int32_t data)
{
    ST_Node* add;

    add = (ST_Node*)malloc(sizeof(ST_Node));

    if (add == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        add-&amp;gt;data = data;
        add-&amp;gt;next = linkedList-&amp;gt;front;
        linkedList-&amp;gt;front = add;

        if (IsLinkedListEmpty(linkedList) == YES) {
            linkedList-&amp;gt;back = add;
        }

        linkedList-&amp;gt;size++;
    }
}

int32_t LinkedListFrontPop(ST_LinkedList* linkedList)
{
    int32_t result = 0;
    ST_Node* del;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        result = linkedList-&amp;gt;front-&amp;gt;data;
        del = linkedList-&amp;gt;front;
        linkedList-&amp;gt;front = linkedList-&amp;gt;front-&amp;gt;next;
        free(del);
        linkedList-&amp;gt;size--;
    }

    return result;
}

void LinkedListBackPush(ST_LinkedList* linkedList, int32_t data)
{
    ST_Node* add;

    add = (ST_Node*)malloc(sizeof(ST_Node));

    if (add == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        add-&amp;gt;data = data;
        add-&amp;gt;next = NULL;
       
        if (IsLinkedListEmpty(linkedList) == YES) {
            linkedList-&amp;gt;front = add;
            linkedList-&amp;gt;back = add;
        }
        else {
            linkedList-&amp;gt;back-&amp;gt;next = add;
            linkedList-&amp;gt;back = add;
        }
        linkedList-&amp;gt;size++;
    }
}

int32_t LinkedListBackPop(ST_LinkedList* linkedList)
{
    int32_t result = 0;
    ST_Node* temp;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        result = linkedList-&amp;gt;back-&amp;gt;data;
        temp = linkedList-&amp;gt;front;

        while (temp-&amp;gt;next != NULL &amp;amp;&amp;amp; temp-&amp;gt;next-&amp;gt;next != NULL) {
            temp = temp-&amp;gt;next;
        }
        temp-&amp;gt;next = NULL;
        free(linkedList-&amp;gt;back);

        linkedList-&amp;gt;back = temp;
        linkedList-&amp;gt;size--;
    }

    return result;
}

void LinkedListInsertion(ST_LinkedList* linkedList, uint32_t position, int32_t data)
{
    int32_t i;
    ST_Node* add;
    ST_Node* cur;

    if (position &amp;gt; linkedList-&amp;gt;size) {
        printf(&quot;position error\n&quot;);
    }
    else if (position == 0) {
        LinkedListFrontPush(linkedList, data);
    }
    else if (position == linkedList-&amp;gt;size) {
        LinkedListBackPush(linkedList, data);
    }
    else {
        add = (ST_Node*)malloc(sizeof(ST_Node));

        if (add == NULL) {
            printf(&quot;heap is full\n&quot;);
        }
        else {
            cur = linkedList-&amp;gt;front;
            for (i = 1; i &amp;lt; position; i++) {
                cur = cur-&amp;gt;next;
            }
            add-&amp;gt;data = data;
            add-&amp;gt;next = cur-&amp;gt;next;
            cur-&amp;gt;next = add;         
            linkedList-&amp;gt;size++;
        }
    }
}

int32_t LinkedListPop(ST_LinkedList* linkedList, uint32_t position)
{
    int32_t result = 0;
    int32_t i;
    ST_Node* cur, *del;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        if (position &amp;gt;= linkedList-&amp;gt;size) {
            printf(&quot;position error\n&quot;);
        }
        else if (position == 0) {
            result = LinkedListFrontPop(linkedList);
        }
        else if (position == linkedList-&amp;gt;size-1) {
            result = LinkedListBackPop(linkedList);
        }
        else {
            cur = linkedList-&amp;gt;front;
            for (i = 1; i &amp;lt; position; i++) {
                cur = cur-&amp;gt;next;
            }
            result = cur-&amp;gt;next-&amp;gt;data;
            del = cur-&amp;gt;next;
            cur-&amp;gt;next = cur-&amp;gt;next-&amp;gt;next;
            free(del);
            linkedList-&amp;gt;size--;
        }
    }

    return result;
}

void LinkedListPrint(ST_LinkedList* linkedList)
{
    ST_Node* cur;
    int32_t i;

    cur = linkedList-&amp;gt;front;
    for (i = 0; i &amp;lt; linkedList-&amp;gt;size; i++) {
        printf(&quot;i=%d, data=%d\n&quot;, i, cur-&amp;gt;data);
        cur = cur-&amp;gt;next;
    }
}


int main()
{
    ST_LinkedList linkedList;
    int32_t i;
    int32_t data[3];

    LinkedListInit(&amp;amp;linkedList);

    for (i = 0; i &amp;lt; 2; i++) {
        LinkedListFrontPush(&amp;amp;linkedList, i);
        LinkedListBackPush(&amp;amp;linkedList, i);
    }
    LinkedListInsertion(&amp;amp;linkedList, 1, 10);
    LinkedListInsertion(&amp;amp;linkedList, 3, 30);

    LinkedListPrint(&amp;amp;linkedList);
    printf(&quot;\n&quot;);

    data[0] = LinkedListPop(&amp;amp;linkedList, 4);
    data[1] = LinkedListFrontPop(&amp;amp;linkedList);
    data[2] = LinkedListBackPop(&amp;amp;linkedList);

    LinkedListPrint(&amp;amp;linkedList);
    
    printf(&quot;popData = %d, %d, %d\n&quot;, data[0], data[1], data[2]);

    LinkedListDelete(&amp;amp;linkedList);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;이중 연결 리스트 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1610406179646&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)


typedef struct ST_Node {
    int32_t data;
    struct ST_Node* next;
    struct ST_Node* prev;
}ST_Node;

typedef struct ST_LinkedList {
    int32_t size;
    ST_Node* front;
    ST_Node* back;
}ST_LinkedList;

void LinkedListInit(ST_LinkedList* linkedList)
{
    linkedList-&amp;gt;size = 0;
    linkedList-&amp;gt;front = NULL;
    linkedList-&amp;gt;back = NULL;
}

void LinkedListDelete(ST_LinkedList* linkedList)
{
    int32_t i;
    ST_Node* del;

    for (i = 0; i &amp;lt; linkedList-&amp;gt;size; i++) {
        del = linkedList-&amp;gt;front;
        linkedList-&amp;gt;front = linkedList-&amp;gt;front-&amp;gt;next;
        free(del);
    }

    LinkedListInit(linkedList);
}

int32_t IsLinkedListEmpty(ST_LinkedList* linkedList)
{
    int32_t result;

    if (linkedList-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

void LinkedListFrontPush(ST_LinkedList* linkedList, int32_t data)
{
    ST_Node* add;

    add = (ST_Node*)malloc(sizeof(ST_Node));

    if (add == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        add-&amp;gt;data = data;
        add-&amp;gt;prev = NULL;
        
        if (IsLinkedListEmpty(linkedList) == YES) {
            add-&amp;gt;next = NULL;
            linkedList-&amp;gt;back = add;
        }
        else {
            add-&amp;gt;next = linkedList-&amp;gt;front;
            linkedList-&amp;gt;front-&amp;gt;prev = add;
        }
        linkedList-&amp;gt;front = add;
        linkedList-&amp;gt;size++;
    }
}

int32_t LinkedListFrontPop(ST_LinkedList* linkedList)
{
    int32_t result = 0;
    ST_Node* del;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        result = linkedList-&amp;gt;front-&amp;gt;data;
        del = linkedList-&amp;gt;front;
        linkedList-&amp;gt;front = linkedList-&amp;gt;front-&amp;gt;next;
        if (linkedList-&amp;gt;front != NULL) {
            linkedList-&amp;gt;front-&amp;gt;prev = NULL;
        }
        free(del);
        linkedList-&amp;gt;size--;
    }

    return result;
}

void LinkedListBackPush(ST_LinkedList* linkedList, int32_t data)
{
    ST_Node* add;

    add = (ST_Node*)malloc(sizeof(ST_Node));

    if (add == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        add-&amp;gt;data = data;
        add-&amp;gt;next = NULL;
        
        if (IsLinkedListEmpty(linkedList) == YES) {
            add-&amp;gt;prev = NULL;
            linkedList-&amp;gt;front = add;
        }
        else {
            add-&amp;gt;prev = linkedList-&amp;gt;back;
            linkedList-&amp;gt;back-&amp;gt;next = add;
        }
        linkedList-&amp;gt;back = add;
        linkedList-&amp;gt;size++;
    }
}

int32_t LinkedListBackPop(ST_LinkedList* linkedList)
{
    int32_t result = 0;
    ST_Node* del;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        result = linkedList-&amp;gt;back-&amp;gt;data;
        
        del = linkedList-&amp;gt;back;
        linkedList-&amp;gt;back = linkedList-&amp;gt;back-&amp;gt;prev;
        if (linkedList-&amp;gt;back != NULL) {
            linkedList-&amp;gt;back-&amp;gt;next = NULL;
        }
        free(del);

        linkedList-&amp;gt;size--;
    }

    return result;
}

void LinkedListInsertion(ST_LinkedList* linkedList, uint32_t position, int32_t data)
{
    int32_t i;
    ST_Node* add;
    ST_Node* cur;

    if (position &amp;gt; linkedList-&amp;gt;size) {
        printf(&quot;position error\n&quot;);
    }
    else if (position == 0) {
        LinkedListFrontPush(linkedList, data);
    }
    else if (position == linkedList-&amp;gt;size) {
        LinkedListBackPush(linkedList, data);
    }
    else {
        add = (ST_Node*)malloc(sizeof(ST_Node));

        if (add == NULL) {
            printf(&quot;heap is full\n&quot;);
        }
        else {
            if (position &amp;lt;= linkedList-&amp;gt;size / 2) {
                cur = linkedList-&amp;gt;front;
                for (i = 0; i &amp;lt; position; i++) {
                    cur = cur-&amp;gt;next;
                }    
            }
            else {
                cur = linkedList-&amp;gt;back;
                int32_t loop = linkedList-&amp;gt;size - position;
                for (i = 1; i &amp;lt; loop; i++) {
                    cur = cur-&amp;gt;prev;
                }
            }
            add-&amp;gt;data = data;
            add-&amp;gt;next = cur;
            add-&amp;gt;prev = cur-&amp;gt;prev;

            cur-&amp;gt;prev = add;
            add-&amp;gt;prev-&amp;gt;next = add;
            linkedList-&amp;gt;size++;
        }
    }
}

int32_t LinkedListPop(ST_LinkedList* linkedList, uint32_t position)
{
    int32_t result = 0;
    int32_t i;
    ST_Node* cur;

    if (IsLinkedListEmpty(linkedList) == YES) {
        printf(&quot;linkedlist is empty\n&quot;);
    }
    else {
        if (position &amp;gt;= linkedList-&amp;gt;size) {
            printf(&quot;position error\n&quot;);
        }
        else if (position == 0) {
            result = LinkedListFrontPop(linkedList);
        }
        else if (position == linkedList-&amp;gt;size - 1) {
            result = LinkedListBackPop(linkedList);
        }
        else {
            if (position &amp;lt;= linkedList-&amp;gt;size / 2) {
                cur = linkedList-&amp;gt;front;
                for (i = 0; i &amp;lt; position; i++) {
                    cur = cur-&amp;gt;next;
                }
            }
            else {
                cur = linkedList-&amp;gt;back;
                int32_t loop = linkedList-&amp;gt;size - position;
                for (i = 1; i &amp;lt; loop; i++) {
                    cur = cur-&amp;gt;prev;
                }
            }
            result = cur-&amp;gt;data;
            cur-&amp;gt;next-&amp;gt;prev = cur-&amp;gt;prev;
            cur-&amp;gt;prev-&amp;gt;next = cur-&amp;gt;next;
            free(cur);
            linkedList-&amp;gt;size--;
        }
    }

    return result;
}

void LinkedListPrint(ST_LinkedList* linkedList)
{
    ST_Node* cur;
    int32_t i;

    cur = linkedList-&amp;gt;front;
    for (i = 0; i &amp;lt; linkedList-&amp;gt;size; i++) {
        printf(&quot;i=%d, data=%d\n&quot;, i, cur-&amp;gt;data);
        cur = cur-&amp;gt;next;
    }
}


int main()
{
    ST_LinkedList linkedList;
    int32_t i;
    int32_t data[3];

    LinkedListInit(&amp;amp;linkedList);

    for (i = 0; i &amp;lt; 2; i++) {
        LinkedListFrontPush(&amp;amp;linkedList, i);
        LinkedListBackPush(&amp;amp;linkedList, i);
    }
    LinkedListInsertion(&amp;amp;linkedList, 1, 10);
    LinkedListInsertion(&amp;amp;linkedList, 3, 30);

    LinkedListPrint(&amp;amp;linkedList);
    printf(&quot;\n&quot;);

    data[0] = LinkedListPop(&amp;amp;linkedList, 4);
    data[1] = LinkedListFrontPop(&amp;amp;linkedList);
    data[2] = LinkedListBackPop(&amp;amp;linkedList);

    LinkedListPrint(&amp;amp;linkedList);

    printf(&quot;popData = %d, %d, %d\n&quot;, data[0], data[1], data[2]);

    LinkedListDelete(&amp;amp;linkedList);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍</category>
      <category>c</category>
      <category>Linked List</category>
      <category>단일 연결 리스트</category>
      <category>링크드리스트</category>
      <category>이중 연결 리스트</category>
      <category>자료구조</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/18</guid>
      <comments>https://elevate-yourself.tistory.com/18#entry18comment</comments>
      <pubDate>Wed, 13 Jan 2021 06:39:40 +0900</pubDate>
    </item>
    <item>
      <title>[c언어] 큐(Queue)</title>
      <link>https://elevate-yourself.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다! 이번 포스팅에서는 큐에 대해서 설명해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료구조 중 하나인 큐(Queue)는 많은 분들이 알고계시고 프로그래밍을 막 시작하신 분들도 한번쯤은 들어봤을만한 대표적인 자료구조 중 하나라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;큐에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐는 입력된 데이터들을 순서대로 저장하고 순서대로 출력하는 자료구조입니다. 큐의 가장 큰 특징은 먼저 들어온 데이터는 먼저 나가는 것입니다. 이것을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;선입선출 또는 FIFO&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이라고 주로 표현합니다. 쉽게 예를 들어서 맛집에서 줄서기를 생각하시면 될 것 같습니다. 먼저 온 사람이 맛집에 먼저 들어가고 나중에 온 사람이 나중에 들어가는 것과 같이 데이터가 관리되게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;큐 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐는 bfs(breath first search)와 같은 탐색 알고리즘 등에서 사용되기도 하지만 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;즉시 처리하지 못하는 상황&lt;/b&gt;&lt;/span&gt;에 주로 사용됩니다. 비동기 시스템에서 주로 사용된다고 생각하시면 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 통신을 예시로 설명하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A쓰레드에서는 데이터를 송신하고 B쓰레드에서는 데이터를 수신하여 쓰레드 간 통신하는 경우로 가정하겠습니다. 이 때 데이터를 송신하는 시점과 수신하는 시점이 달라서 비동기인 상황에서는 데이터를 송신했을 때 수신하는 쓰레드에서 수신 데이터를 즉시 처리할 수 없습니다. 이러한 상황에서 A쓰레드에서 데이터들을 큐에 입력하고 B쓰레드에서는 처리 가능한 시간에 큐에서 데이터를 출력하여 처리함으로써 비동기 상황에서 데이터를 문제없이 수신하여 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우 뿐만 아니라 데이터가 수신될 때 수신된 데이터 파싱과 같은 작업을 즉시 처리할 수 있는 시간이 부족한 경우 큐에 데이터만 입력하고 데이터가 수신되지 않거나 여유있는 시간에 큐에서 데이터를 출력하여 문제없이 처리 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;큐 구현 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큐는 배열과 링크드리스트를 사용하여 구현할 수 있습니다. 배열의 경우 선형큐와 원형큐로 구분할 수 있지만 선형큐의 경우 사용하기에 적절하지 않기 때문에 원형큐를 사용하게 됩니다. c++의 경우 STL을 사용하여 쉽게 검증된 큐를 사용하실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 배열을 통해 원형큐를 구현하는 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;back값은 데이터가 입력 되어야 할 인덱스 위치, front값은 데이터가 출력 되어야 할 인덱스 위치입니다. 마지막 인덱스까지 데이터를 입력하거나 출력했을 때(back값 또는 front값이 마지막 인덱스 값일 때)는 다시 첫번째 인덱스(back값 또는 front값이 0)에 데이터를 입력하거나 출력하도록 구현합니다. 최대로 입력될 수 있는 크기를 고려하여 배열을 크기를 선정하는 것이 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림은 큐 크기가 4인 큐에 데이터를 1 ~ 5까지 push하고 pop을 한번하는 과정입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv7ule/btqR1D7AVTZ/MaRCc6eUln4ZpKiRuwya51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv7ule/btqR1D7AVTZ/MaRCc6eUln4ZpKiRuwya51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv7ule/btqR1D7AVTZ/MaRCc6eUln4ZpKiRuwya51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv7ule%2FbtqR1D7AVTZ%2FMaRCc6eUln4ZpKiRuwya51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo2KbE/btqR3S4vQ8w/kAQS1fmHgJPRRoKluP0iC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo2KbE/btqR3S4vQ8w/kAQS1fmHgJPRRoKluP0iC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo2KbE/btqR3S4vQ8w/kAQS1fmHgJPRRoKluP0iC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo2KbE%2FbtqR3S4vQ8w%2FkAQS1fmHgJPRRoKluP0iC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c56HVp/btqRVpoGexD/lJu8JVyRYxOs1KwhnYUbn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c56HVp/btqRVpoGexD/lJu8JVyRYxOs1KwhnYUbn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c56HVp/btqRVpoGexD/lJu8JVyRYxOs1KwhnYUbn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc56HVp%2FbtqRVpoGexD%2FlJu8JVyRYxOs1KwhnYUbn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 링크드리스트를 통해 큐를 구현하는 경우 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;front가 가르키는 노드를 출력하고 back의 다음 노드에 입력된 노드를 연결하여 구현하도록 합니다. front는 가장 앞의 노드를 가르키게 되며 back은 가장 마지막의 노드를 가르키게 됩니다. 데이터를 입력할 때는 마지막 노드의 뒤에 추가된 데이터 노드를 이어서 입력하게 되고, 데이터를 출력할 때는 첫번째 노드의 데이터를 출력하고 다음 노드를 첫번째 노드로 가르키도록 합니다. 링크드리스트를 통해서 큐를 구현하면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;큐의 최대 크기를 고려하지 않고 구현할 수 있는 장점&lt;/b&gt;&lt;/span&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림은 큐에 1 ~ 3까지 push하고 1번 pop을 한번하는 과정입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd2dyM/btqR9lZpBRW/V5Owmiqg7EOtel4rK0TyH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd2dyM/btqR9lZpBRW/V5Owmiqg7EOtel4rK0TyH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd2dyM/btqR9lZpBRW/V5Owmiqg7EOtel4rK0TyH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd2dyM%2FbtqR9lZpBRW%2FV5Owmiqg7EOtel4rK0TyH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qWx4x/btqSbachj1P/J8MJnRJKpWECeNe7gI9ykk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qWx4x/btqSbachj1P/J8MJnRJKpWECeNe7gI9ykk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qWx4x/btqSbachj1P/J8MJnRJKpWECeNe7gI9ykk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqWx4x%2FbtqSbachj1P%2FJ8MJnRJKpWECeNe7gI9ykk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpWizk/btqSjA2hzaC/V5HsBUIba1SMAH1X6J8XpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpWizk/btqSjA2hzaC/V5HsBUIba1SMAH1X6J8XpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpWizk/btqSjA2hzaC/V5HsBUIba1SMAH1X6J8XpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpWizk%2FbtqSjA2hzaC%2FV5HsBUIba1SMAH1X6J8XpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배열을 이용한 큐 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1609373656661&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

typedef struct {
    int32_t front;
    int32_t back;
    int32_t size;
    int32_t bufSize;
    int32_t* buf;
}ST_Queue;

int32_t IsQueueEmpty(ST_Queue * queue)
{
    int32_t result;

    if (queue-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

int32_t IsQueueFull(ST_Queue* queue)
{
    int32_t result;

    if (queue-&amp;gt;size == queue-&amp;gt;bufSize) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

int32_t QueueSize(ST_Queue* queue)
{
    int32_t result;

    result = queue-&amp;gt;size;

    return result;
}

int32_t QueueInit(ST_Queue* queue, int32_t queueLength)
{
    int32_t result;

    queue-&amp;gt;buf = (int32_t*)malloc(sizeof(int32_t) * queueLength);

    if (queue-&amp;gt;buf != NULL) {
        queue-&amp;gt;front = 0;
        queue-&amp;gt;back = 0;
        queue-&amp;gt;size = 0;
        queue-&amp;gt;bufSize = queueLength;
        memset(queue-&amp;gt;buf, 0, (sizeof(int32_t) * queueLength));
        result = YES;
    }
    else {
        result = NO;
    }
    
    return result;
}

void QueueDelete(ST_Queue* queue)
{
    free(queue-&amp;gt;buf);
}

void QueuePush(ST_Queue* queue, int32_t data)
{
    if (IsQueueFull(queue) == YES) {
        printf(&quot;queue is full\n&quot;);
    }
    else {
        queue-&amp;gt;buf[queue-&amp;gt;back] = data;
        queue-&amp;gt;back++;
        queue-&amp;gt;size++;

        if (queue-&amp;gt;back == queue-&amp;gt;bufSize) {
            queue-&amp;gt;back = 0;
        }
    }
}

int32_t QueuePop(ST_Queue* queue)
{
    int32_t result = 0;

    if (IsQueueEmpty(queue) == YES) {
        printf(&quot;queue is emtpy\n&quot;);
    }
    else {
        result = queue-&amp;gt;buf[queue-&amp;gt;front];
        queue-&amp;gt;front++;
        queue-&amp;gt;size--;

        if (queue-&amp;gt;front == queue-&amp;gt;bufSize) {
            queue-&amp;gt;front = 0;
        }
    }

    return result;
}

int main()
{
    #define QUEUE_LENGTH (4)

    ST_Queue queue;
    int32_t i, data, loop;

    if (QueueInit(&amp;amp;queue, QUEUE_LENGTH) == NO) {
        printf(&quot;queue init fail\n&quot;);
    }

    /* push test */
    for (i = 0; i &amp;lt; QUEUE_LENGTH; i++) {
        QueuePush(&amp;amp;queue, i);
        printf(&quot;pushData = %d, queueSize = %d\n&quot;, i, QueueSize(&amp;amp;queue));
    }

    data = QUEUE_LENGTH;
    QueuePush(&amp;amp;queue, data);
    printf(&quot;pushData = %d, queueSize = %d\n&quot;, data, QueueSize(&amp;amp;queue));

    /* pop test */
    loop = QueueSize(&amp;amp;queue);
    for (i = 0; i &amp;lt; loop; i++) {
        data = QueuePop(&amp;amp;queue);
        printf(&quot;popData = %d, queueSize = %d\n&quot;, data, QueueSize(&amp;amp;queue));
    }
    
    data = QueuePop(&amp;amp;queue);
    printf(&quot;popData = %d, queueSize = %d\n&quot;, data, QueueSize(&amp;amp;queue));

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;링크드리스트를 이용한 큐 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1609485119277&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

#define NO (0)
#define YES (!NO)

typedef struct ST_Node{
    int32_t data;
    ST_Node* next;
}ST_Node;

typedef struct {
    ST_Node* front;
    ST_Node* back;
    int32_t size;
}ST_Queue;

int32_t IsQueueEmpty(ST_Queue* queue)
{
    int32_t result;

    if (queue-&amp;gt;size == 0) {
        result = YES;
    }
    else {
        result = NO;
    }

    return result;
}

int32_t QueueSize(ST_Queue* queue)
{
    int32_t result;

    result = queue-&amp;gt;size;

    return result;
}

int32_t QueueInit(ST_Queue* queue)
{
    int32_t result = YES;

    queue-&amp;gt;front = NULL;
    queue-&amp;gt;back = NULL;
    queue-&amp;gt;size = 0;    

    return result;
}

void QueueDelete(ST_Queue* queue)
{
    int32_t i;
    ST_Node* temp;

    for (i = 0; i &amp;lt; queue-&amp;gt;size; i++) {
        temp = queue-&amp;gt;front;
        queue-&amp;gt;front = queue-&amp;gt;front-&amp;gt;next;
        free(temp);
    }

    queue-&amp;gt;front = NULL;
    queue-&amp;gt;back = NULL;
    queue-&amp;gt;size = 0;
}

void QueuePush(ST_Queue* queue, int32_t data)
{
    ST_Node* addNode;

    addNode = (ST_Node*)malloc(sizeof(ST_Node));

    if (addNode == NULL) {
        printf(&quot;heap is full\n&quot;);
    }
    else {
        addNode-&amp;gt;data = data;
        addNode-&amp;gt;next = NULL;

        if (IsQueueEmpty(queue) == YES) {
            queue-&amp;gt;front = addNode;
            queue-&amp;gt;back = addNode;
        }
        else {
            queue-&amp;gt;back-&amp;gt;next = addNode;
            queue-&amp;gt;back = addNode;
        }
        queue-&amp;gt;size++;
    }
}

int32_t QueuePop(ST_Queue* queue)
{
    int32_t result = 0;
    ST_Node* del;

    if (IsQueueEmpty(queue) == YES) {
        printf(&quot;queue is emtpy\n&quot;);
    }
    else {
        result = queue-&amp;gt;front-&amp;gt;data;
        del = queue-&amp;gt;front;
        queue-&amp;gt;front = queue-&amp;gt;front-&amp;gt;next;
        queue-&amp;gt;size--;

        free(del);
    }

    return result;
}

int main()
{
#define QUEUE_LENGTH (4)

    ST_Queue queue;
    int32_t i, data, loop;

    if (QueueInit(&amp;amp;queue) == NO) {
        printf(&quot;queue init fail\n&quot;);
    }

    /* push test */
    for (i = 0; i &amp;lt; QUEUE_LENGTH; i++) {
        QueuePush(&amp;amp;queue, i);
        printf(&quot;pushData = %d, queueSize = %d\n&quot;, i, QueueSize(&amp;amp;queue));
    }

    /* pop test */
    loop = QueueSize(&amp;amp;queue);
    for (i = 0; i &amp;lt; loop; i++) {
        data = QueuePop(&amp;amp;queue);
        printf(&quot;popData = %d, queueSize = %d\n&quot;, data, QueueSize(&amp;amp;queue));
    }
    
    data = QueuePop(&amp;amp;queue);

    QueueDelete(&amp;amp;queue);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 큐에 대한 설명을 마치겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C언어</category>
      <category>Queue</category>
      <category>링크드리스트 큐</category>
      <category>원형큐</category>
      <category>자료구조</category>
      <category>코딩</category>
      <category>큐</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/17</guid>
      <comments>https://elevate-yourself.tistory.com/17#entry17comment</comments>
      <pubDate>Fri, 1 Jan 2021 17:08:27 +0900</pubDate>
    </item>
    <item>
      <title>c언어/c++ do while(0)</title>
      <link>https://elevate-yourself.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다! 이번 포스팅에서는 do while(0)에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;do while문에 대해서 모르시는 분은 아래의 포스팅을 먼저 읽어보시는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elevate-yourself.tistory.com/15&quot;&gt;2020/12/18 - [분류 전체보기] - c언어/c++ do while문&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1608219116033&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;c언어/c++ do while문&quot; data-og-description=&quot;안녕하세요 업글입니다. 이번 포스팅에서는 do while문에 대해서 설명드리겠습니다. do while문에 대한 설명 while문에 대해서 잘 모르시는 분은 지난번 포스팅한 while문에 대해서 먼저 읽어보시는 것&quot; data-og-host=&quot;elevate-yourself.tistory.com&quot; data-og-source-url=&quot;https://elevate-yourself.tistory.com/15&quot; data-og-url=&quot;https://elevate-yourself.tistory.com/15&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bELC4l/hyIB0aOql8/IKQqaK8MtKxVHJa1uTLlfk/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530,https://scrap.kakaocdn.net/dn/Mzy0c/hyIBZJLg9W/WIDqY3NpQYzz35gsuPkSCk/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530,https://scrap.kakaocdn.net/dn/djHdd5/hyICc99L76/bSp5eRr3Qsw0hGstxkS2T0/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530&quot;&gt;&lt;a href=&quot;https://elevate-yourself.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elevate-yourself.tistory.com/15&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bELC4l/hyIB0aOql8/IKQqaK8MtKxVHJa1uTLlfk/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530,https://scrap.kakaocdn.net/dn/Mzy0c/hyIBZJLg9W/WIDqY3NpQYzz35gsuPkSCk/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530,https://scrap.kakaocdn.net/dn/djHdd5/hyICc99L76/bSp5eRr3Qsw0hGstxkS2T0/img.png?width=605&amp;amp;height=530&amp;amp;face=0_0_605_530');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;c언어/c++ do while문&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서는 do while문에 대해서 설명드리겠습니다. do while문에 대한 설명 while문에 대해서 잘 모르시는 분은 지난번 포스팅한 while문에 대해서 먼저 읽어보시는 것&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elevate-yourself.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;do while(0)에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;do while(0)는 조건이 무조건 거짓이기 때문에 해당하는 코드를 반복하지 않고 1회만 수행하게 됩니다. 이렇게 되면 do while(0)를 사용하지 않고 일반적으로 코드를 작성하는 것과 동일한 결과를 출력하게 됩니다. 그런데 왜 do while(0)를 사용하는 것일까요? 제가 생각했을 때는 2가지 경우가 있습니다. 첫번째로는 코드의 가독성, 두번째는 &lt;span style=&quot;color: #333333;&quot;&gt;매크로 함수 구현&lt;/span&gt;입니다. 하나씩 상세하게 설명드리도록 하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;코드의 가독성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순차적으로 정상임을 확인 해야 하는 경우를 예시로 설명 드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 3개 open하는 코드를 예시로 들겠습니다. 설명을 위하여 약간 억지(?)인 것 같기도 합니다만 아래와 같은 경우의 정상인지 비정상인지 확인하는 코드를 작성하는 경우는 꽤나 많다고 생각합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608561902403&quot; class=&quot;c++ arduino&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define FILE_NUM (3)
#define NORMAL (-1)

int main()
{
	FILE* fp[FILE_NUM];
	uint32_t errorFile = NORMAL;

	fp[0] = fopen(&quot;file0.txt&quot;, &quot;r&quot;);

	if (fp[0] != NULL) {
		fp[1] = fopen(&quot;file1.txt&quot;, &quot;r&quot;);

		if (fp[1] != NULL) {
			fp[2] = fopen(&quot;file2.txt&quot;, &quot;r&quot;);

			if (fp[2] != NULL) {
				// 로직
			}
			else {
				errorFile = 2;
			}
		}
		else {
			errorFile = 1;
		}
	}
	else {
		errorFile = 0;
	}

	printf(&quot;errorFile = %d&quot;, errorFile);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0번 파일이 정상적으로 open되었을 때 1번 파일을 open하고 1번 파일이 정상적으로 open되었을 때 2번 파일을 open하고 2번 파일이 정상적으로 open되었을 때 어떠한 로직을 실행하는 코드입니다. if문 안에 if문이 있고 또 if문이 있어서 코드의 가독성이 떨어지는 편입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 경우 do while(0)과 break문을 사용하여 깔끔하게 표현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608561902403&quot; class=&quot;c++ arduino&quot; style=&quot;margin: 20px auto 0px; display: block; overflow: auto; padding: 15px; color: #383a42; background: #f6f7f8; font-size: 14px; border-radius: 3px; font-family: Menlo, Consolas, Monaco, monospace; border: 1px solid #dddddd; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define FILE_NUM (3)
#define NORMAL (-1)

int main()
{
	FILE* fp[FILE_NUM];
	uint32_t errorFile = NORMAL;

	do {
		fp[0] = fopen(&quot;file0.txt&quot;, &quot;r&quot;);

		if (fp[0] == NULL) {
			errorFile = 0;
			break;
		}

		fp[1] = fopen(&quot;file1.txt&quot;, &quot;r&quot;);

		if (fp[1] == NULL) {
			errorFile = 1;
			break;
		}

		fp[2] = fopen(&quot;file2.txt&quot;, &quot;r&quot;);

		if (fp[2] == NULL) {
			errorFile = 2;
			break;
		}
	} while (0);

	// 로직

	printf(&quot;errorFile = %d&quot;, errorFile);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드와 동일한 동작을 하게 되지만 if문이 중첩되지 않기 때문에 코드의 가독성이 좋아지게 됩니다. 또한 do while(0) 내부에서만 사용되는 변수가 있는 경우 do while(0) 내부에서 변수를 선언하여 사용함으로써 코드를 보다 깔끔하게 작성할 수 있습니다. 이러한 경우에 do while(0)를 사용하는 것을 추천드립니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;매크로 함수 구현&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 오픈소스에서 &lt;span style=&quot;color: #333333;&quot;&gt;do while(0)를 사용하여 &lt;/span&gt;매크로함수를 작성하는 것을 많이 봐왔습니다. 왜 매크로 함수 구현 시 do while(0)를 사용하는지 설명드리겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608472408746&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c) printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c);\
									c = a + b;\
									printf(&quot;c = %d\n&quot;, c)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		MACRO_FUNCTION_ADD(a, b, c);
	

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 구현했을 때 전처리기 결과는 아래와 같이 되게 됩니다. 이는 코드가 의도한 바와 다르게 동작하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608472471691&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c);
		c = a + b;
		printf(&quot;c = %d\n&quot;, c);
	

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UeSzF/btqQ1NhOREc/wqXSiUGRB2GysobQTEcDp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UeSzF/btqQ1NhOREc/wqXSiUGRB2GysobQTEcDp0/img.png&quot; data-alt=&quot;결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UeSzF/btqQ1NhOREc/wqXSiUGRB2GysobQTEcDp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUeSzF%2FbtqQ1NhOREc%2FwqXSiUGRB2GysobQTEcDp0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의도한 바는 if 조건이 참인 경우 printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c) / c = a+b / printf(&quot;c = %d\n&quot;, c) 3줄의 코드를 실행하고 if 조건이 거짓인 경우 모든 줄의 코드가 실행되지 않아야합니다. 그러나 if 조건이 참인 경우에는 의도한 바와 같이 동작하지만 &lt;span style=&quot;color: #333333;&quot;&gt;if 조건이 거짓인 경우 &lt;span style=&quot;color: #333333;&quot;&gt;c = a+b / printf(&quot;c = %d\n&quot;, c) 2줄의 코드만 실행하게되어 의도한 바와 다르게 코드가 실행되게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 아래의 코드와 같이 else가 있는 경우 컴파일러 에러가 발생하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608558928281&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c) printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c);\
									c = a + b;\
									printf(&quot;c = %d\n&quot;, c)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf(&quot;else\n&quot;);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfKTlG/btqQZwniH5L/d4ld7U4KMNRcKKaMc3xpwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfKTlG/btqQZwniH5L/d4ld7U4KMNRcKKaMc3xpwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfKTlG/btqQZwniH5L/d4ld7U4KMNRcKKaMc3xpwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfKTlG%2FbtqQZwniH5L%2Fd4ld7U4KMNRcKKaMc3xpwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 아래와 같이 { }를 추가하여 코드를 수정한 후 실행 해보도록 하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608559144872&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c)	{\
										printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c); \
										c = a + b; \
                                        printf(&quot;c = %d\n&quot;, c); \
									}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
		
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-alt=&quot;if(1) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDcxjW%2FbtqQLkPFlcB%2FMv6B7wW46UN7nnWwjj83n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(1) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; data-alt=&quot;if(0) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnBJ5C%2FbtqQ3gjMn5Q%2F2ayOIu4Tm2r69knsYYEQNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(0) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if가 참, 거짓인 경우 모두 의도한 바와 같이 동작하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 아래의 코드는 위에서 컴파일러 에러가 발생하는 코드와 같이 동일하게 에러가 발생하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608559489087&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c)	{\
										printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c); \
										c = a + b; \
                                        printf(&quot;c = %d\n&quot;, c); \
									}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf(&quot;else\n&quot;);
    
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CvF8p/btqQ1LK6Qnr/WH7YFyvvkAVmuLNkzMm45k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CvF8p/btqQ1LK6Qnr/WH7YFyvvkAVmuLNkzMm45k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CvF8p/btqQ1LK6Qnr/WH7YFyvvkAVmuLNkzMm45k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCvF8p%2FbtqQ1LK6Qnr%2FWH7YFyvvkAVmuLNkzMm45k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;do while(0)를 사용하여 매크로 함수를 작성한 후 코드를 실행해보도록 하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608559893584&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c) do{\
										printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c);\
										c = a + b;\
										printf(&quot;c = %d\n&quot;, c);\
									}while(0)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
		
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-alt=&quot;if(1) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDcxjW%2FbtqQLkPFlcB%2FMv6B7wW46UN7nnWwjj83n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(1) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; data-alt=&quot;if(0) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnBJ5C/btqQ3gjMn5Q/2ayOIu4Tm2r69knsYYEQNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnBJ5C%2FbtqQ3gjMn5Q%2F2ayOIu4Tm2r69knsYYEQNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(0) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;if가 참, 거짓인 경우 모두 의도한 바와 같이 동작하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;또한, do while(0)를 사용하면 아래의 코드에서 컴파일러 에러가 발생하지 않고 코드가 의도한 대로 동작하게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1608559995550&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

#define MACRO_FUNCTION_ADD(a, b, c) do{\
										printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c);\
										c = a + b;\
										printf(&quot;c = %d\n&quot;, c);\
									}while(0)

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (1)
		MACRO_FUNCTION_ADD(a, b, c);
	else
		printf(&quot;else\n&quot;);
        
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; data-alt=&quot;if(1) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dDcxjW/btqQLkPFlcB/Mv6B7wW46UN7nnWwjj83n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdDcxjW%2FbtqQLkPFlcB%2FMv6B7wW46UN7nnWwjj83n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(1) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bmb4h/btqQNpb7s7v/zHZ6gFpUwKLek2pGapjIf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bmb4h/btqQNpb7s7v/zHZ6gFpUwKLek2pGapjIf0/img.png&quot; data-alt=&quot;if(0) 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bmb4h/btqQNpb7s7v/zHZ6gFpUwKLek2pGapjIf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBmb4h%2FbtqQNpb7s7v%2FzHZ6gFpUwKLek2pGapjIf0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;if(0) 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;do while(0)를 제외하고 위의 2가지 경우에서도 아래의 코드와 같이 if와 else에 { }만 추가해준다면 코드가 의도한 대로 동작되고 컴파일 에러가 발생하지 않습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1608560212294&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#define MACRO_FUNCTION_ADD(a, b, c)		printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c); \
										c = a + b; \
										printf(&quot;c = %d\n&quot;, c)

//#define MACRO_FUNCTION_ADD(a, b, c)		{\
										printf(&quot;a=%d, b=%d, c=%d\n&quot;, a, b, c); \
										c = a + b; \
										printf(&quot;c = %d\n&quot;, c); \
										}

int main()
{
	int32_t a, b, c;
	a = 1;
	b = 2;
	c = 0;

	if (0) {
		MACRO_FUNCTION_ADD(a, b, c);
	}
	else{
		printf(&quot;else\n&quot;);
	}
		
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 사용자에 따라서 if에 코드가 한줄만 실행되는 경우 { }를 생략하고 작성하는 경우가 있기 때문에 매크로 함수를 작성하실 때는 do while(0)를 필수적으로 사용하는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, if문 사용 시 코드가 한줄만 실행되더라도 { }를 사용하여 코드를 작성하시는 것을 추천드립니다. 위와 같은 상황을 미리 방지하기 위함입니다. 코드가 간결할 때는 이러한 문제를 쉽게 찾을 수 있지만 코드가 복잡해지면 많은 시간을 낭비할수도 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 do while(0)에 대한 설명을 마치도록 하겠습니다!&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/16</guid>
      <comments>https://elevate-yourself.tistory.com/16#entry16comment</comments>
      <pubDate>Mon, 21 Dec 2020 23:51:13 +0900</pubDate>
    </item>
    <item>
      <title>c언어/c++ do while문</title>
      <link>https://elevate-yourself.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서는 do while문에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;do while문에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문에 대해서 잘 모르시는 분은 지난번 포스팅한 while문에 대해서 먼저 읽어보시는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://elevate-yourself.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2020/12/17 - [분류 전체보기] - c언어/c++ while문&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1608216946099&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;c언어/c++ while문&quot; data-og-description=&quot;안녕하세요 업글입니다. 이번 포스팅에서는 반복문중 하나인 while문에 대해서 설명 드리도록 하겠습니다. while문에 대한 설명 c언어 및 c++에서 반복문은 while문, do while문, for문이 있습니다. 이 반&quot; data-og-host=&quot;elevate-yourself.tistory.com&quot; data-og-source-url=&quot;https://elevate-yourself.tistory.com/14&quot; data-og-url=&quot;https://elevate-yourself.tistory.com/14&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NBP0X/hyICfMymlp/vPN0cd5bp53vjTvkrdMSTk/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533,https://scrap.kakaocdn.net/dn/QbCcc/hyIB7ueVzw/lSGWUa16kaUKSD934lkASK/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533,https://scrap.kakaocdn.net/dn/KMvnP/hyIAQHDiCf/HgIUBmHSKNIb50Q3GQnWQK/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533&quot;&gt;&lt;a href=&quot;https://elevate-yourself.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://elevate-yourself.tistory.com/14&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NBP0X/hyICfMymlp/vPN0cd5bp53vjTvkrdMSTk/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533,https://scrap.kakaocdn.net/dn/QbCcc/hyIB7ueVzw/lSGWUa16kaUKSD934lkASK/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533,https://scrap.kakaocdn.net/dn/KMvnP/hyIAQHDiCf/HgIUBmHSKNIb50Q3GQnWQK/img.png?width=579&amp;amp;height=533&amp;amp;face=0_0_579_533');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;c언어/c++ while문&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서는 반복문중 하나인 while문에 대해서 설명 드리도록 하겠습니다. while문에 대한 설명 c언어 및 c++에서 반복문은 while문, do while문, for문이 있습니다. 이 반&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;elevate-yourself.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;do while문은 while문과 거의 동일하나 하나의 차이가 있습니다. while전에 do가 있듯이 반복하기 전에 뭔가를 해라라는 의미입니다. 즉, while문처럼 반복하기 전에 먼저 코드를 수행하고 반복하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b62yRP/btqQwndFaw3/pTUls1AV6aiocN0Vyat331/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b62yRP/btqQwndFaw3/pTUls1AV6aiocN0Vyat331/img.png&quot; data-alt=&quot;do while문 동작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b62yRP/btqQwndFaw3/pTUls1AV6aiocN0Vyat331/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb62yRP%2FbtqQwndFaw3%2FpTUls1AV6aiocN0Vyat331%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;do while문 동작&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림처럼 ①에서 먼저 코드를 실행하고 ②에서 조건을 확인한 후 다시&lt;span style=&quot;color: #333333;&quot;&gt;① 코드를 실행하고 다시&lt;span style=&quot;color: #333333;&quot;&gt;②으로 이동하는 것을 반복하고 거짓인 경우 ③으로 이동하여 do while문을 탈출하게 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;또 한번 강조하지만 중요한점은 먼저 무조건 코드를 실행한 후 조건을 확인한다는 점입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;문법적으로 while(조건)뒤에 세미클론을 붙여줘야 한다는점도 꼭 기억하시길 바랍니다. 세미클론이 없으면 컴파일러에서 에러로 출력하게됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;do while문 예제&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1608217984421&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	do {
		printf(&quot;value = %d\n&quot;, value);

		value++;
	} while (value == 0);

	printf(&quot;do while후 value = %d\n&quot;, value);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cj7RXs/btqQE9Zxd4i/P0LTF1WRsaEPjAUk94qInk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cj7RXs/btqQE9Zxd4i/P0LTF1WRsaEPjAUk94qInk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cj7RXs/btqQE9Zxd4i/P0LTF1WRsaEPjAUk94qInk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcj7RXs%2FbtqQE9Zxd4i%2FP0LTF1WRsaEPjAUk94qInk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value가 1일 때 value == 0의 조건에서 거짓이기 때문에 printf와 value++을 1번만 실행하고 do while문을 탈출하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1608218097300&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	do {
		printf(&quot;value = %d\n&quot;, value);

		value++;
	} while (value == 1);

	printf(&quot;do while후 value = %d\n&quot;, value);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLD43S/btqQDGceJ4G/G9vh0gtdkL98iTZ2iWntVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLD43S/btqQDGceJ4G/G9vh0gtdkL98iTZ2iWntVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLD43S/btqQDGceJ4G/G9vh0gtdkL98iTZ2iWntVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLD43S%2FbtqQDGceJ4G%2FG9vh0gtdkL98iTZ2iWntVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서는 value가 1이 되고 value == 1의 조건에서 참이기 때문에 do while구문을 1회더 반복 실행한 후 value가 2가되어 조건이 거짓이 되기 때문에 do while문을 탈출하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;do while문에서 break 키워드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문 포스팅에서 설명한 것처럼 break 키워드는 반복문을 탈출하는 키워드입니다. do while의 경우도 while문과 동일하게 break 키워드의 위치에 오게되면 do while문을 바로 탈출하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608218814396&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	do {
		printf(&quot;value = %d\n&quot;, value);
		
		if (value == 0) {
			break;
		}
		value++;
	} while (value == 1);

	printf(&quot;do while후 value = %d\n&quot;, value);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EWN3P/btqQpsG56YJ/nqUUFkDkwJf2kKD8BI7v41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EWN3P/btqQpsG56YJ/nqUUFkDkwJf2kKD8BI7v41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EWN3P/btqQpsG56YJ/nqUUFkDkwJf2kKD8BI7v41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEWN3P%2FbtqQpsG56YJ%2FnqUUFkDkwJf2kKD8BI7v41%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value의 초기 값은 0이므로 break문을 만나게 됩니다. break문을 만나고 바로 do while문을 탈출하게 되므로 밑의 코드(value++)은 실행되지 않게됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;do while문에서 continue 키워드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문 포스팅에서 설명한 것처럼 continue 키워드는 반복문의 조건을 다시 확인하는키워드입니다. 그러므로 do while의 경우도 while문과 동일하게 continue 키워드를 만나게 되면 조건을 확인하는 위치인 while(조건)으로 이동하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608218526012&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;
	int32_t continueCount = 0;

	do {
		printf(&quot;value = %d, continueCount = %d\n&quot;, value, continueCount);
		if (continueCount == 3) {
			break;
		}

		if (value == 0) {
			continueCount++;
			continue;
		}
		value++;
	} while (value == 0);

	printf(&quot;do while후 value = %d, continueCount = %d\n&quot;, value, continueCount);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3BsH1/btqQE8M5rxx/0O7JCWs2OwItkGLszyFS9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3BsH1/btqQE8M5rxx/0O7JCWs2OwItkGLszyFS9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3BsH1/btqQE8M5rxx/0O7JCWs2OwItkGLszyFS9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3BsH1%2FbtqQE8M5rxx%2F0O7JCWs2OwItkGLszyFS9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value는 0이기때문에 continue문을 만나게됩니다. continue후 while(value == 0);으로 바로 이동하기 때문에 value++은 실행되지 않습니다. 그러므로 총 continue를 3회 만나고 조건을 3회 확인한 후 continueCount가 3일 때 break를 만나게되어 do while반복문을 탈출하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 do while문에 대한 설명을 마치겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>Break</category>
      <category>C++</category>
      <category>continue</category>
      <category>C언어</category>
      <category>do while</category>
      <category>While</category>
      <category>반복문</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/15</guid>
      <comments>https://elevate-yourself.tistory.com/15#entry15comment</comments>
      <pubDate>Fri, 18 Dec 2020 00:28:47 +0900</pubDate>
    </item>
    <item>
      <title>c언어/c++ while문</title>
      <link>https://elevate-yourself.tistory.com/14</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서는 반복문중 하나인 while문에 대해서 설명 드리도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;while문에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c언어 및 c++에서 반복문은 while문, do while문, for문이 있습니다. 이 반복문들 중에서 while문에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;while문은 조건이 참인 경우 해당하는 코드를 수행하고 조건이 거짓일 때까지 코드를 반복적으로 수행하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOF4BZ/btqQpsUENyr/so7PZfhWugJ7faGatigHu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOF4BZ/btqQpsUENyr/so7PZfhWugJ7faGatigHu1/img.png&quot; data-alt=&quot;while문 동작&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOF4BZ/btqQpsUENyr/so7PZfhWugJ7faGatigHu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOF4BZ%2FbtqQpsUENyr%2Fso7PZfhWugJ7faGatigHu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;while문 동작&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 그림과 같이 while문은 ①에서 조건을 확인하고 참인 경우 ②의 코드를 실행하고 다시①으로 이동하는 것을 반복하고 거짓인 경우 ③으로 이동하여 while문을 탈출하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;while문 예제&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1608213216209&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	while (value &amp;lt; 5) {
		printf(&quot;value = %d\n&quot;, value);
		value++;
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/myLQK/btqQzSdoi3k/4F8HcoZE7sthLfnuT4V9L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/myLQK/btqQzSdoi3k/4F8HcoZE7sthLfnuT4V9L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/myLQK/btqQzSdoi3k/4F8HcoZE7sthLfnuT4V9L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmyLQK%2FbtqQzSdoi3k%2F4F8HcoZE7sthLfnuT4V9L1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value가 0, 1, 2, 3, 4일 때는 참이기 때문에 printf문을 실행하고 value를 1씩 증가시킵니다. value가 5가되고 조건이 거짓이 되기때문에 while문을 탈출하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;break 키워드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;break 키워드는 반복문을 탈출하는 키워드입니다. while문을 반복 실행하다가 break문의 위치에 오게되면 바로 while문을 탈출하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608215674182&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	while (1) {
		printf(&quot;value = %d\n&quot;, value);

		if (value == 5) {
			break;
		}
		value++;
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxac4f/btqQE87ncrd/YTIx0Rrs7Jg1xy2TkBbqMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxac4f/btqQE87ncrd/YTIx0Rrs7Jg1xy2TkBbqMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxac4f/btqQE87ncrd/YTIx0Rrs7Jg1xy2TkBbqMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbxac4f%2FbtqQE87ncrd%2FYTIx0Rrs7Jg1xy2TkBbqMK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 while(1)이기 때문에 조건은 항상 참이므로 무한 반복하게 됩니다. 그러나 value가 5일 때 break문을 만나기때문에 바로 while문을 탈출하게 됩니다. break문의 밑에 코드(value++)는 수행되지 않게 됩니다. 그러므로 결과에서 break후 value값은 5가 되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;continue 키워드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;continue 키워드는 반복문의 조건을 다시 확인하는 키워드입니다. while문을 반복 실행하다가 continue키워드의 위치에 오게되면 while문의 조건을 확인하는 위치로 이동하여 조건을 다시 확인하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608216479998&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;
	int32_t continueCount = 0;

	while (1) {
		printf(&quot;value = %d, continueCount = %d\n&quot;, value, continueCount);

		if (continueCount == 3) {
			break;
		}

		if (value == 3) {
			continueCount++;
			continue;
		}
		value++;
	}

	printf(&quot;break후 value = %d, continueCount = %d\n&quot;, value, continueCount);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CAVul/btqQCAiZyit/ceoA1KiHycerjH9wMpNrd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CAVul/btqQCAiZyit/ceoA1KiHycerjH9wMpNrd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CAVul/btqQCAiZyit/ceoA1KiHycerjH9wMpNrd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCAVul%2FbtqQCAiZyit%2FceoA1KiHycerjH9wMpNrd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value가 3일때 continue 키워드를 만나게 됩니다. continue 키워드를 만나게되면 밑의 코드(value++)는 실행되지 않으며 while(1)의 위치로 이동하여 조건을 재확인하게됩니다. while문을 탈출한 후에 value의 값은 3이 되게 됩니다. continue의 경우 해당하는 조건에 아래의 코드를 실행하지 않게할 때 사용 하실 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상 while문과 break, continue문에 대한 설명을 마치도록 하겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>Break</category>
      <category>C++</category>
      <category>continue</category>
      <category>C언어</category>
      <category>While</category>
      <category>반복문</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/14</guid>
      <comments>https://elevate-yourself.tistory.com/14#entry14comment</comments>
      <pubDate>Thu, 17 Dec 2020 23:53:34 +0900</pubDate>
    </item>
    <item>
      <title>c언어/c++ if 조건문</title>
      <link>https://elevate-yourself.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요 업글입니다. 이번 포스팅에서 if 조건문에 대해서 설명드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적인 생각으로 if문은 c언어 및 c++뿐만아니라 모든 프로그래밍 언어에서 가장 중요한? 없어서는 안되는? 중요하고 필수적으로 쓰여야 하는 문법이라고 생각합니다. 학부 시절에 포인터와 같은 초보자가 알지 못하고 이해하기 힘든 문법이 많은 상황에서도 조건문과 반복문을 통해서 대부분의 기능을 구현 했었던 기억이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;if 조건문에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if 조건문은 괄호안의 조건이 참인 경우 if 조건문에 해당하는 코드를 실행하게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608126937701&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(조건){
	// 조건이 참인 경우 { } 안의 코드 실행
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 조건이 참이냐 거짓이냐를 판단하는 기준은 if(0)인 경우 거짓이고 if(0외에 숫자)인 경우 참입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608127148541&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(참){
	// { } 안에 있는 코드가 실행된다.
}

if(거짓){
	// { } 안에 있는 코드가 실행되지 않는다.
}
// 해당 위치에서 코드 실행 시작&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건이 참인 경우 { }안에 있는 코드들이 실행되며 조건이 거짓인 경우 { }안에 있는 코드들이 실행되지 않고 { } 아래에서 코드 실행이 시작되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 예제 코드를 보면서 설명드리겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608129521317&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;

int32_t Getvalue() 
{
	int32_t result;

	result = 0;

	return result;
}


int main()
{
	int32_t value;

	value = Getvalue();

	if (value == 0) {
		printf(&quot;value = 0\n&quot;);
	}

	if (value == 1) {
		printf(&quot;value = 1\n&quot;);
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 value는 0이기 때문에 첫번째 조건문에서는 참이고 두번째 조건문에서는 거짓이므로 아래의 그림과 같은 결과를 출력하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOLL2a/btqQjnyZl3h/ryOXo3VC7yTiuxUxAYsZ70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOLL2a/btqQjnyZl3h/ryOXo3VC7yTiuxUxAYsZ70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOLL2a/btqQjnyZl3h/ryOXo3VC7yTiuxUxAYsZ70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOLL2a%2FbtqQjnyZl3h%2FryOXo3VC7yTiuxUxAYsZ70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;if, else if, else에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if를 사용하여 해당하는 조건일 때만 if문의 { } 내부 코드를 실행 할 수 있습니다. 여러 조건이 필요한 경우에 어떻게 나타낼수 있을까요? 아래의 코드와 같이 if문을 여러 개 사용하여 나타낼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608130071708&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;

int32_t Getvalue()
{
	int32_t result;

	result = rand() % 3;

	return result;
}


int main()
{
	int32_t value;

	value = Getvalue();

	if (value == 0) {
		printf(&quot;value = 0\n&quot;);
	}

	if (value == 1) {
		printf(&quot;value = 1\n&quot;);
	}

	if (value == 2) {
		printf(&quot;value = 2\n&quot;);
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서는 value가 0, 1, 2일 때 각각 조건에 대하여 if문을 사용하였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위의 코드에서 value가 0이라고 가정했을 때 첫번째 if문에서 참이기 때문에 해당하는 코드를 실행하게됩니다. 두번째, 세번째 if문에서는 value가 0이기 때문에 거짓이지만 조건을 확인하게 됩니다&lt;/span&gt;. 이러한 경우에 if, else if, else를 사용하여 처리할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608130491740&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;

int32_t Getvalue()
{
	int32_t result;

	result = rand() % 3;

	return result;
}


int main()
{
	int32_t value;

	value = Getvalue();

	if (value == 0) {
		printf(&quot;value = 0\n&quot;);
	}
	else if (value == 1) {
		printf(&quot;value = 1\n&quot;);
	}
	else{
		printf(&quot;value = 2\n&quot;);
	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if, else if, else를 사용했을 때 value가 0이 아닌 경우 그 다음 else if 조건인 value가 1인지 확인하고 1이면 해당하는 코드를 실행하고 value가 1이 아닌 경우 else에 해당하는 코드를 실행하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if만 사용하는 경우와 다르게 value가 0인 경우 if문의 조건이 참이기 때문에 해당하는 코드만 실행하고 else if, else에 대한 조건은 확인하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단락평가(short circuit evaluation)에 대한 설명&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1608131290989&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(1 || 0) // 첫번째 항에서 이미 1이기 때문에 || 뒤의 조건은 확인하지 않고 1로 출력
(0 &amp;amp;&amp;amp; 1) // 첫번째 항에서 이미 0이기 때문에 &amp;amp;&amp;amp; 뒤의 조건은 확인하지 않고 0으로 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 보듯이 단락평가란 ||연산자를 사용하는 경우 첫번째 항에서 1이면 뒤의 조건에 관계없이 1이되기 때문에뒤의 조건을 확인하지 않고 1을 출력하며 &amp;amp;&amp;amp;연산자를 사용하는 경우 첫번째 항에서 0이면 뒤의 조건에 관계없이 0이되기 때문에 뒤의 조건을 확인하지 않고 0을 출력하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if 조건문에서 ||, &amp;amp;&amp;amp;연산자를 사용하여 조건식을 구성하는 경우가 많으므로 단락평가를 고려하여 보다 코드를 효율적으로 작성하실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 통해서 설명드리겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608131990562&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;
	int32_t count = 0;

	// value가 0이므로 첫번째 항이 참이 되기 때문에 || 뒤의 조건 실행 X
	if (value == 0 || (count = 1)) {
		printf(&quot;|| short circuit evaluation\n&quot;);
	}

	// value가 0이므로 첫번째 항이 거짓이 되기 때문에 || 뒤의 조건 실행 X
	if (value == 1 &amp;amp;&amp;amp; (count = 1)) {
		printf(&quot;&amp;amp;&amp;amp; short circuit evaluation\n&quot;);
	}
	
	printf(&quot;count = %d\n&quot;, count);

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/THtwT/btqQt6bo4O6/JIhLOMwL8L6Wivh4GHItXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/THtwT/btqQt6bo4O6/JIhLOMwL8L6Wivh4GHItXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/THtwT/btqQt6bo4O6/JIhLOMwL8L6Wivh4GHItXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTHtwT%2FbtqQt6bo4O6%2FJIhLOMwL8L6Wivh4GHItXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단락평가로 인해서 첫번째 if문에서 value == 0은 참이기 때문에 || 뒤의 조건을 실행하지 않게되고 두번째 if문에서 value == 1은 거짓이기 때문에 &amp;amp;&amp;amp; 뒤의 조건을 실행하지 않게됩니다. count가 0인 것을 보아 뒤의 조건을 실행하지 않은 것을 확인할 수 있습니다. 그러므로 ||를 사용하는 경우 참이 될 가능성이 높은 조건을 앞에 작성하고 &amp;amp;&amp;amp;를 사용하는 경우 거짓이 될 가능성이 높은 조건을 뒤에 작성하면 보다 효율적으로 속도를 빠르게 할 수 있습니다. PC와 같은 환경에서는 큰 차이가 없으므로 고민하지 않아도 되지만, 가격이 저렴한 MCU와 같은 하드웨어에서 속도를 최적화 해야하는 경우 적용을 할 수도 있을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;if 조건문 사용 시 주의 사항&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if문에서 ==연산자를 사용하는 경우 실수로 ==대신 =을 입력할 수 있습니다. 이러한 경우 if문은 의도하지 않은 동작을 하게 됩니다. &quot;= 0&quot;인 경우 무조건 거짓으로 판단되며 &quot;= 0이외 숫자&quot;인 경우 무조건 거짓으로 판단하게 됩니다. 이러한 경우 컴파일러에서 오류로 출력해주지만 에러로 출력해주지 않기 때문에 주의할 필요가 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1608132870451&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h &amp;gt;


int main()
{
	int32_t value = 0;

	// 의도한 코드 : value == 0
	if (value = 0) {
		printf(&quot;value가 0이므로 무조건 실행되지 않는다.&quot;);
	}

	// 의도한 코드 : value == 1
	if (value = 1) {
		printf(&quot;value가 1이므로 무조건 실행된다.&quot;);
	}

	// 실수를 예방하기 위한 코드
	// 0 = value가 되면 오류 출력
	if (0 == value) {

	}

	// 실수를 예방하기 위한 코드
	// 1 = value가 되면 오류 출력
	if (1 == value) {

	}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 첫번째, 두번째 if문은 실수로 인해서 작성된 코드이고 첫번째 if문은 무조건 실행될 수 없으며 두번째 if문은 무조건 실행되게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 실수를 예방하기 위해서 상수를 왼쪽에 두는 방법이 있습니다. 상수를 왼쪽에 두게 되면 상수는 변경될 수 없기 때문에 에러가 발생되게 됩니다. 그러나 보편적으로 상수를 오른쪽으로 두기 때문에 가독성은 조금 떨어질 것으로 생각됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if문을 포함한 if/else if/else, 단락평가, if문 주의사항에 대한 포스팅은 이상 마치도록 하겠습니다.&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>C++</category>
      <category>C언어</category>
      <category>iF</category>
      <category>if else if else</category>
      <category>short circuit evaluation</category>
      <category>단락평가</category>
      <category>조건문</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <author>업글</author>
      <guid isPermaLink="true">https://elevate-yourself.tistory.com/13</guid>
      <comments>https://elevate-yourself.tistory.com/13#entry13comment</comments>
      <pubDate>Thu, 17 Dec 2020 00:40:14 +0900</pubDate>
    </item>
  </channel>
</rss>