<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>다유데브</title>
    <link>https://dayudev.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 21 Aug 2026 11:46:59 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>다유데브</managingEditor>
    <item>
      <title>0. 개요</title>
      <link>https://dayudev.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 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;제가 처음에 말씀드렸듯이 예제 프로그램을 직접 입력하고 컴파일을 하셨다면 지금쯤 vim에 좀 익숙해지고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c언어에 대해서도 익숙해 졌으리라 생각됩니다.&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;예제프로그램은 반드시 vim으로 직접 입력해 보고 gcc로 컴파일을 해보고 실행해보고 궁금한게 있으면 예제 프로그램을 수정해서 실행해 보면서&amp;nbsp; 익히셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이방법이 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;심화과정에서는 증권사 투자정보 시스템 기능하는 프로젝트를 목표로 강의를 진행하려고 합니다.&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;최종 목표에 필요한 모듈개념, 라이브러리 만들기, makefile, cmake 등 과 같은 개발시 유용한 툴에 대해서 진행하도록 하겠씁니다.&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;/p&gt;</description>
      <category>리눅스 C-언어 심화과정</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/26</guid>
      <comments>https://dayudev.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 8 Dec 2022 08:36:20 +0900</pubDate>
    </item>
    <item>
      <title>19. #include,#define,#ifdef ..</title>
      <link>https://dayudev.tistory.com/25</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발시 자주 사용되는 전처리기 이해하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전처리기는 gcc 컴파일 하기전에 이루어지는 작업입니다.&lt;/li&gt;
&lt;li&gt;전처리기는 #include, #define, #ifdef, #undef, 등 여러가지 형태가 있습니다.&lt;/li&gt;
&lt;li&gt;이전 강의에서 배운 #pragma도 전처리기의 한 형태입니다.&lt;/li&gt;
&lt;li&gt;여기서는 자주 사용되는 #include, #define, #ifdef 문에 대해서 알아봅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669164108602&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 사용자가 작성한 헤더파일을 포함시킬 수 있습니다.
#include &quot;my_header.h&quot;

// 매크로를 정의할 수 있습니다.
#define	MAX_ARRAY	100

// 매크로를 조건연산자로도 정의할 수 있습니다.
// a,b중 작은값을 구하는 매크로입니다.
#define MIN_LEN(a,b) (((a)&amp;lt;(b))?(a):(b))

// 매크로를 함수로도 정의할 수 있습니다.
#define ADD_PRINT(a,b) \
{ \
	printf(&quot;%d + %d = %d\n&quot;, (a), (b), (a) + (b)); \
}

// #define으로 정의된것을 제거할 수 있습니다.
#undef ADD_PRINT

// #define를 조건문으로 분기가 가능합니다.
#ifndef MY_HEADER
#include &quot;my_header.h&quot;
#define	MY_HEADER
...
#endif&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) #include문 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 구조체 예제 프로그램 struct8.c에서 구조체 정의를 stock.h 헤더파일로 분리해 봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi stock.h&lt;/p&gt;
&lt;pre id=&quot;code_1669164757886&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#pragma pack(1)

// 값만을 가지는 struct
typedef struct {
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
} PRICE_ST;

// 주식 현재가 struct 의 새로운 타입을 정의
// struct의 멤버로 struct를 가질수 있습니다.
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    PRICE_ST price;
    double qty;             // 거래량
} CURRENT_PRICE_ST;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct9.c&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669164909623&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
// 구조체가 정의된 stock.h 헤더파일을 포함시킵니다.
#include &quot;stock.h&quot;

// call-by-value로 구조체 사용하기
void print_value(CURRENT_PRICE_ST valuePrice) {
    printf(&quot;--- print_value ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, valuePrice.code);
    printf(&quot;주식명  :[%s]\n&quot;, valuePrice.name);
    printf(&quot;현재가  :[%d]\n&quot;, valuePrice.price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, valuePrice.price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, valuePrice.price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, valuePrice.price.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, valuePrice.qty);
}

// call-by-reference로 구조체 사용하기
void print_reference(CURRENT_PRICE_ST *ptrPrice) {
    printf(&quot;--- print_reference ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, ptrPrice-&amp;gt;code);
    printf(&quot;주식명  :[%s]\n&quot;, ptrPrice-&amp;gt;name);
    printf(&quot;현재가  :[%d]\n&quot;, ptrPrice-&amp;gt;price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, ptrPrice-&amp;gt;qty);
}

void main() {
    // struct _tagCurrentPrice의 선언
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, {61000, 60500, 62000, 60300}, 1234500.0};
    // 포인터 변수
    CURRENT_PRICE_ST *ptrPrice_st = &amp;amp;currentPrice_st;

    // call-by-value 값 출력
    print_value(currentPrice_st);

    // call-by-reference 값 출력
    print_reference(ptrPrice_st);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669164975501&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✹✭ ᐅ gcc -o struct9 struct9.c
~/c-lecture (master ✘)✹✭ ᐅ ./struct9
--- print_value ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
--- print_reference ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✹✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 구조체 강의 예제 struct8 과 동일하게 출력됩니다.&lt;/li&gt;
&lt;li&gt;앞으로 배우시게 되겠지만 하나의 실행파일은 여러개의 c프로그램으로 만들어 질 수 있습니다.&lt;br /&gt;여러개의 c프로그램에서 이런 구조체 정의가 필요하면 c프로그램안에 똑같은 구조체 정의를 넣어야 합니다.&lt;br /&gt;이렇게 여러곳에서 필요한 내용을 헤더파일로 따로 만들어서 필요한곳에 #include문으로 정의해 주시면 간단히 사용 가능합니다.&lt;/li&gt;
&lt;li&gt;#include &amp;lt;stdio.h&amp;gt; 와 다르게 #include &quot;stock.h&quot;로 코딩되어 있습니다.&amp;nbsp;&lt;br /&gt;이처럼 c언어에서 제공하는 헤더파일은 &amp;lt;&amp;gt; 로 사용되고, 여러분들이 작성한 헤더파일은 &quot;&quot;로 사용합니다.&lt;br /&gt;그러니 여러분들이 만든 헤더파일을 포함할때는 #include &quot;header.h&quot; 로 작성하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) #define문 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi def.c&lt;/p&gt;
&lt;pre id=&quot;code_1669166423210&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// 값을 재정의할 수 있습니다.
#define MAX_ARRAY   100

#define STOCK_NAME  &quot;주식명&quot;

// 매크로를 조건연산자로도 정의할 수 있습니다.
// a,b중 작은값을 구하는 매크로입니다.
#define MIN_LEN(a,b) (((a)&amp;lt;(b))?(a):(b))

// 매크로를 함수로도 정의할 수 있습니다.
#define ADD_PRINT(a,b) \
{ \
    printf(&quot;%d + %d = %d\n&quot;, (a), (b), (a) + (b)); \
}

void main() {
    char my_array[MAX_ARRAY];
    int min_len;

    printf(&quot;MAX_ARRAY = [%d] : my_array 크기 = [%ld]\n&quot;, MAX_ARRAY, sizeof(my_array));

    printf(&quot;STOCK_NAME = [%s]\n&quot;, STOCK_NAME);

    // 작은값을 구하는 매크로
    min_len = MIN_LEN(10, 5);
    printf(&quot;MIN_LEN = [%d]\n&quot;, min_len);
    
    // 출력매크로
    ADD_PRINT(3, 5);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669166459122&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✹✭ ᐅ gcc -o def def.c
~/c-lecture (master ✘)✹✭ ᐅ ./def
MAX_ARRAY = [100] : my_array 크기 = [100]
STOCK_NAME = [주식명]
MIN_LEN = [5]
3 + 5 = 8
~/c-lecture (master ✘)✹✭ ᐅ&lt;/code&gt;&lt;/pre&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&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#define 으로 값을 재정의 해서 사용합니다. 의미가 있는 숫자,문자열을 의미있는 이름으로 재정의해서 사용합니다.&lt;br /&gt;숫자 100를 MAX_ARRAY로 정의, &quot;주식명&quot;을 STOCK_NAME으로 정의해서 프로그램안에서는 MAX_ARRAY를 사용하면 100으로 치환되고, STOCK_NAME을 사용하면 &quot;주식명&quot;으로 치환됩니다.&lt;/li&gt;
&lt;li&gt;매크로를 정의해서 사용합니다. 두개의 변수중 작은값을 구하고자 할때 if문을 사욯할수도 있고, 조건연산자를 사용할수도 있고 이렇게 매크로를 사용해서 사용할 수 도 있습니다.&lt;br /&gt;min_len = MIN_LEN(10, 5); 숫자 10, 5 중 작은값을 리턴해 줍니다.&lt;br /&gt;MIN_LEN은 (10 &amp;lt; 5 ? 10 : 5)로 정의됩니다. 그래서 10은 5보다 작지 않기 때문에 거짓(false)인 5가 리턴됩니다.&lt;/li&gt;
&lt;li&gt;매크로는 좀 더 길게 정의 될수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669167123722&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
// 매크로를 함수로도 정의할 수 있습니다.
#define ADD_PRINT(a,b) \
{ \
    printf(&quot;%d + %d = %d\n&quot;, (a), (b), (a) + (b)); \
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#define문은 한 줄로 정의가 됩니다. 그런데 코딩을 하다 보면 한줄이 길어 지는 경우도 있습니다. 이런경우&lt;br /&gt;c언어에서는 &lt;b&gt;줄의 마지막에 \ (역슬래쉬) 를 넣고&lt;/b&gt; 다음줄에 계속해서 작성해도 한줄로 인식을 합니다.&lt;br /&gt;즉, 위의 문장은&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669167425618&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 매크로를 함수로도 정의할 수 있습니다.
#define ADD_PRINT(a,b) { printf(&quot;%d + %d = %d\n&quot;, (a), (b), (a) + (b)); }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이렇게 정의될 수 있습니다. 그런데 이렇게 한줄로 코딩을 하다보면 읽기가 어려운 경우가 있습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 그래서&amp;nbsp; \ (역슬래쉬)로 분리해서 읽기 편안하게 작성하는 경우가 있습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; ADD_PRINT(3, 5)로 불려지면 정의된 printf문이 실행됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#undef 문은 거의 사용하는 경우가 없습니다. 기능은 #define으로 정의된걸 제거합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669167655415&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    // 출력매크로
    ADD_PRINT(3, 5);
#undef ADD_PRINT
    // 출력매크로
    ADD_PRINT(3, 5);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#undef ADD_PRINT 문 다음에 ADD_PRINT(3, 5);를 다시 호출하면 컴파일시 오류가 발생합니다.&lt;br /&gt;ADD_PRINT가 정의가 안되어 있어서 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) #ifdef문 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi def2.c&lt;/p&gt;
&lt;pre id=&quot;code_1669168182603&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#define APPLE   &quot;apple&quot;
#define ORANGE  &quot;orange&quot;

void main() {

#ifdef APPLE
    printf(&quot;APPLE 정의 : [%s]\n&quot;, APPLE);
#endif

#ifndef ORANGE
    printf(&quot;ORANGE 정의되어 있지 않음\n&quot;);
#else
    printf(&quot;ORANGE 정의 : [%s]\n&quot;, ORANGE);
#endif

#ifdef GRAPE
    printf(&quot;GRAPE 정의 : [%s]\n&quot;, GRAPE);
#elif MANGO
    printf(&quot;MANGO 정의 : [%s]\n&quot;, MANGO);
#else
    printf(&quot;정의되어 있지 않음\n&quot;);
#endif

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669168211436&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✹✭ ᐅ gcc -o def2 def2.c
~/c-lecture (master ✘)✹✭ ᐅ ./def2
APPLE 정의 : [apple]
ORANGE 정의 : [orange]
정의되어 있지 않음
~/c-lecture (master ✘)✹✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;#ifdef문은 #define으로 정의가 되어 있으면 참(true)이고 정의가 안되어 있으면 거짓(false)입니다.&lt;br /&gt;if문과 동일하게 동작합니다.&lt;br /&gt;#ifdef APPLE&amp;nbsp; ==&amp;gt; APPLE이 #define으로 정의가 되어 있어서 참입니다.&lt;/li&gt;
&lt;li&gt;#ifndef문은 #ifdef문과 반대로 정의가 안되어 있으면 참이고 정의되어 있으면 거짓입니다.&lt;br /&gt;#ifndef ORANGE ==&amp;gt; ORANGE가 정의 되어 있어서 거짓입니다. 그래서 #else 문의 printf()문이 실행됩니다.&lt;/li&gt;
&lt;li&gt;if문과 마찬가지로 #ifdef ~ #elif ~ #elif ~ #else문으로 사용됩니다.&lt;br /&gt;#ifdef GRAPE 문은 거짓이므로 다음문 #elif MANGO를 체크합니다. 그런데 MANGO도 정의가 안되어 있어서 거짓이므로 #else문이 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;※ #ifdef, #ifndef 문은 끝에 반드시 #endif문으로 끝이 납니다.&lt;/b&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;3-4) #ifndef - #include문 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ※ 사용자 헤더파일과 자주 사용되는 패턴을 알아보겠습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 위에서 작성한 stock.h를 수정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi stock.h&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669169006322&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#ifndef STOCK_HEADER
#define STOCK_HEADER

#pragma pack(1)

// 값만을 가지는 struct
typedef struct {
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
} PRICE_ST;

// 주식 현재가 struct 의 새로운 타입을 정의
// struct의 멤버로 struct를 가질수 있습니다.
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    PRICE_ST price;
    double qty;             // 거래량
} CURRENT_PRICE_ST;

#endif&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작성한 헤더파일을 포함시켜서 사용하는데 프로그램이 복잡해지고 여러 헤더파일을 사용하다 보면 1번이상 포함시키는 경우도 발생할 수 있습니다. 그러면 컴파일시 중복 오류가 발생합니다. 그래서 1번만 포함시키려고 #ifndef문을 사용합니다.&lt;/li&gt;
&lt;li&gt;헤더파일 처음에 #ifndef&amp;nbsp; STOCK_HEADER 로 체크를 합니다. 처음에는 당연 STOCK_HEADER가 정의가 안되어 있어서 참이므로 아래문장이 실행됩니다.&amp;nbsp;&lt;br /&gt;#define STOCK_HEADER 정의가 안되어 있어서 정의를 합니다. 그리고 구조체 정의문이 나오고 마지막에 #endif문으로 끝이 납니다. 그럼 또 다시 stock.h가 포함이 되면 #ifndef STOCK_HEADER문에서 STOCK_HEADER문이 정의가 되어있으니 #endif문으로 바로 끝이 납니다. 이렇게 헤더파일 중복 포함을 배제합니다.&lt;/li&gt;
&lt;li&gt;강의가 진행되면서 헤더파일을 만드는일이 있으면 이런방식으로 작성하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>#define</category>
      <category>#ifdef</category>
      <category>#include</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>Linux</category>
      <category>리눅스</category>
      <category>전처리기</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/25</guid>
      <comments>https://dayudev.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 23 Nov 2022 11:17:10 +0900</pubDate>
    </item>
    <item>
      <title>18. 구조체 중첩</title>
      <link>https://dayudev.tistory.com/24</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체안의 구조체 이해하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;pre id=&quot;code_1669014753132&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 값만을 가지는 struct
typedef struct {
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
} PRICE_ST;

// 주식 현재가 struct 의 새로운 타입을 정의
// struct의 멤버로 struct를 가질수 있습니다.
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    PRICE_ST price;
    double qty;             // 거래량
} CURRENT_PRICE_ST;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 멤버로 다른 구조체가 될 수 있습니다.&lt;/li&gt;
&lt;li&gt;CURRENT_PRICE_ST안에 다른 구조체 PRICE_ST 가 멤버가 될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct8.c&lt;/p&gt;
&lt;pre id=&quot;code_1669014931937&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#pragma pack(1)

// 값만을 가지는 struct
typedef struct {
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
} PRICE_ST;

// 주식 현재가 struct 의 새로운 타입을 정의
// struct의 멤버로 struct를 가질수 있습니다.
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    PRICE_ST price;
    double qty;             // 거래량
} CURRENT_PRICE_ST;

// call-by-value로 구조체 사용하기
void print_value(CURRENT_PRICE_ST valuePrice) {
    printf(&quot;--- print_value ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, valuePrice.code);
    printf(&quot;주식명  :[%s]\n&quot;, valuePrice.name);
    printf(&quot;현재가  :[%d]\n&quot;, valuePrice.price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, valuePrice.price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, valuePrice.price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, valuePrice.price.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, valuePrice.qty);
}

// call-by-reference로 구조체 사용하기
void print_reference(CURRENT_PRICE_ST *ptrPrice) {
    printf(&quot;--- print_reference ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, ptrPrice-&amp;gt;code);
    printf(&quot;주식명  :[%s]\n&quot;, ptrPrice-&amp;gt;name);
    printf(&quot;현재가  :[%d]\n&quot;, ptrPrice-&amp;gt;price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, ptrPrice-&amp;gt;qty);
}

void main() {
    // struct _tagCurrentPrice의 선언
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, {61000, 60500, 62000, 60300}, 1234500.0};
    // 포인터 변수
    CURRENT_PRICE_ST *ptrPrice_st = &amp;amp;currentPrice_st;

    // call-by-value 값 출력
    print_value(currentPrice_st);

    // call-by-reference 값 출력
    print_reference(ptrPrice_st);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669014969992&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct8 struct8.c
~/c-lecture (master ✘)✭ ᐅ ./struct8
--- print_value ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
--- print_reference ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CURRENT_PRICE_ST 안에 PRICE_ST 를 멤버로 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;선언과 동시에 값을 할당할때 구조체는 {} 로 초기화하는데 구조체안의 구조체는 { {} }로 초기화합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;call-by-value에서 PRICE_ST 멤버의 접근은 구조체 멤버의 접근과 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669015546038&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, {61000, 60500, 62000, 60300}, 1234500.0};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; currentPrice_st의 멤버 price는 구조체이므로 다시 {}를 사용해서 {61000, 60500, 62000, 60300}로 초기화합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1669015207517&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    printf(&quot;현재가  :[%d]\n&quot;, valuePrice.price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, valuePrice.price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, valuePrice.price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, valuePrice.price.lowPrice);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;call-by-reference의 포인터로써의 접근은 ptrPrice포인터 변수의 -&amp;gt; price의 멤버는 . 로 접근가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669015255511&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    printf(&quot;현재가  :[%d]\n&quot;, ptrPrice-&amp;gt;price.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, ptrPrice-&amp;gt;price.lowPrice);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 다른 멤버처럼 PRICE_ST의 price는 -&amp;gt; 로 접근가능합니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;ptrPrice-&amp;gt;price&lt;/b&gt; 여기에 price는 구조체이므로 구조체의 멤버로 접근하는 . 멤버명을 사용합니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; ptrPrice-&amp;gt;&lt;b&gt;price.currentPrice&lt;/b&gt;&lt;/p&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>Pointer</category>
      <category>struct</category>
      <category>리눅스</category>
      <category>포인터</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/24</guid>
      <comments>https://dayudev.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 21 Nov 2022 16:24:10 +0900</pubDate>
    </item>
    <item>
      <title>17. 구조체와 포인터</title>
      <link>https://dayudev.tistory.com/23</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 크기 알아보기&lt;/li&gt;
&lt;li&gt;#pragma pack 에 대해서 이해하기&lt;/li&gt;
&lt;li&gt;구조체를 함수 파라메타로 사용하기&lt;/li&gt;
&lt;li&gt;구조체 포인터인 경우 멤버접근 방법 알아보기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;pre id=&quot;code_1669006958631&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 구조체의 크기
sizeof(CURRENT_PRICE_ST);

// call-by-value로 구조체 사용하기
void print_value(CURRENT_PRICE_ST valuePrice) {
    printf(&quot;주식코드:[%s]\n&quot;, valuePrice.code);
    ...
}

// call-by-reference로 구조체 사용하기
void print_reference(CURRENT_PRICE_ST *ptrPrice) {
    printf(&quot;주식코드:[%s]\n&quot;, ptrPrice-&amp;gt;code);
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 크기도 sizeof 연산자로 구할수 있습니다.&lt;br /&gt;정의된 구조체의 크기&lt;br /&gt;sizeof(CURRENT_PRICE_ST);&lt;br /&gt;선언된 구조체의 크기&lt;br /&gt;sizeof(currentPrice_st);&lt;/li&gt;
&lt;li&gt;call-by-value는 구조체를 그대로 받아서 같은 방식으로 사용합니다. &lt;br /&gt;구조체 변수명에 &lt;b&gt;.&lt;/b&gt; 멤버명으로 사용합니다.&lt;/li&gt;
&lt;li&gt;call-by-reference는 구조체에 대한 포인터로 받아서 사용합니다.&lt;br /&gt;이때 구조체 멤버는 구조체 포인터명에 -&amp;gt;멤버명으로 사용하면 됩니다.&lt;br /&gt;code멤버에 대한 접근은 ptrPrice-&amp;gt;code로 사용합니다.&lt;br /&gt;또한 호출하는곳에서는 변수의 포인터처럼 &lt;b&gt;&amp;amp;&lt;/b&gt; 를 붙여서 호출하면 포인터를 넘겨줍니다.&lt;br /&gt;print_reference(&amp;amp;currentPrice_st);&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) 크기 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct4.c&lt;/p&gt;
&lt;pre id=&quot;code_1669008852455&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// 주식 현재가 struct 의 새로운 타입을 정의
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
} CURRENT_PRICE_ST;

void main() {
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};

    // 정의된 CURRENT_PRICE_ST의 크기
    printf(&quot;CURRENT_PRICE 크기[%ld]\n&quot;, sizeof(CURRENT_PRICE_ST));

    // currentPrice_st 크기
    printf(&quot;currentPrice_st 크기[%ld]\n&quot;, sizeof(currentPrice_st));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669008914927&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct4 struct4.c
~/c-lecture (master ✘)✭ ᐅ ./struct4
CURRENT_PRICE 크기[120]
currentPrice_st 크기[120]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typedef로 정의된 CURRENT_PRICE_ST로 크기를 구하거나 선언된 currentPrice_st로 구해도 값은 동일합니다.&lt;/li&gt;
&lt;li&gt;CURRENT_PRICE_ST의 멤버의 각각을 sizeof()로 구해보면&amp;nbsp;&lt;br /&gt;code[10]:10바이트&lt;br /&gt;code[80]:80바이트&lt;br /&gt;int : 4바이트 * 4개 (currentPrice, startPrice, highPrice, lowPrice) : 16바이트&lt;br /&gt;double : 8바이트&lt;br /&gt;모두 합해보면 114입니다. 그런데 sizeof()로 출력해 보면 120이 출력된걸 보실수 있습니다.&lt;br /&gt;구조체를 선언할때 시스템에서는 구조체중 가장 크기가 큰 타입 (여기서는 double qty)의 배수로 메모리를 할당해 줍니다. 그래서 차이가 생깁니다.&amp;nbsp;&lt;br /&gt;이렇게 차이가 나면 개발시 구조체를 사용할때 문제가 발생합니다.&lt;br /&gt;그럼 이런 차이를 없애는 방법은 어떻게 하면 될까요?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) #pragma pack 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct5.c&lt;/p&gt;
&lt;pre id=&quot;code_1669009578103&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#pragma pack(1)

// 주식 현재가 struct 의 새로운 타입을 정의
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
} CURRENT_PRICE_ST;

void main() {
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};

    // 정의된 CURRENT_PRICE_ST의 크기
    printf(&quot;CURRENT_PRICE 크기[%ld]\n&quot;, sizeof(CURRENT_PRICE_ST));

    // currentPrice_st 크기
    printf(&quot;currentPrice_st 크기[%ld]\n&quot;, sizeof(currentPrice_st));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669009609807&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct5 struct5.c
~/c-lecture (master ✘)✭ ᐅ ./struct5
CURRENT_PRICE 크기[114]
currentPrice_st 크기[114]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행을 보시면 114가 출력된걸 보실 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;#pragma&amp;nbsp;pack(1)&lt;/b&gt;&lt;br /&gt;struct문의 가장 큰 타입의 크기로 메모리가 할당되는것을&amp;nbsp; 1바이트 단위로 할당하라는 명령어 입니다.&lt;br /&gt;개발중에 struct를 정의를 정확한 크기를 사용하실 경우 #pragma pack(1) 를 넣고 작업하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) 함수 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct6.c&lt;/p&gt;
&lt;pre id=&quot;code_1669010092703&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#pragma pack(1)

// 주식 현재가 struct 의 새로운 타입을 정의
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
} CURRENT_PRICE_ST;

// call-by-value로 구조체 사용하기
void print_value(CURRENT_PRICE_ST valuePrice) {
    printf(&quot;--- print_value(%p) ---\n&quot;, &amp;amp;valuePrice);       // 메모리주소 출력
    printf(&quot;주식코드:[%s]\n&quot;, valuePrice.code);
    printf(&quot;주식명  :[%s]\n&quot;, valuePrice.name);
    printf(&quot;현재가  :[%d]\n&quot;, valuePrice.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, valuePrice.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, valuePrice.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, valuePrice.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, valuePrice.qty);
}

// call-by-reference로 구조체 사용하기
void print_reference(CURRENT_PRICE_ST *ptrPrice) {
    printf(&quot;--- print_reference(%p) ---\n&quot;, ptrPrice);  // 메모리주소 출력
    printf(&quot;주식코드:[%s]\n&quot;, ptrPrice-&amp;gt;code);
    printf(&quot;주식명  :[%s]\n&quot;, ptrPrice-&amp;gt;name);
    printf(&quot;현재가  :[%d]\n&quot;, ptrPrice-&amp;gt;currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, ptrPrice-&amp;gt;startPrice);
    printf(&quot;고가    :[%d]\n&quot;, ptrPrice-&amp;gt;highPrice);
    printf(&quot;저가    :[%d]\n&quot;, ptrPrice-&amp;gt;lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, ptrPrice-&amp;gt;qty);
}

void main() {
    // struct _tagCurrentPrice의 선언
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};

    // currentPrice_st 크기와 메모리 주소 출력
    printf(&quot;currentPrice_st 주소[%p]\n&quot;, &amp;amp;currentPrice_st);

    // call-by-value 값 출력
    print_value(currentPrice_st);

    // call-by-reference 값 출력
    print_reference(&amp;amp;currentPrice_st);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669010185299&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct6 struct6.c
~/c-lecture (master ✘)✭ ᐅ ./struct6
currentPrice_st 주소[0x7fff83553cb0]
--- print_value(0x7fff83553c30) ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
--- print_reference(0x7fff83553cb0) ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 내용을 출력하는 함수를 call-by-value, call-by-reference로 호출합니다.&lt;/li&gt;
&lt;li&gt;call-by-value 방식&lt;br /&gt;print_value(currentPrice_st);&lt;br /&gt;출력된 내용을 보시면 이전 강의에서 설명드린대로 메모리 주소가 다릅니다.&lt;br /&gt;currentPrice_st 주소와 print_value() 주소가 다른 이유는 call-by-value방식은 함수가 호출될때 파라메타로 받은 변수를 새롭게 메모리가 할당됩니다. 즉, currentPrice_st&amp;nbsp; 의 크기 114바이트 만큼 메모리가 새롭게 할당됩니다.&lt;br /&gt;개발을 하다 보면 수백,수천되는 구조체를 정의하고 사용하는 경우가 많습니다. 그럼 이렇게 call-by-value로 호출을 하면 함수가 호출될때 마다 구조체의 크기 만큼 메모리가 할당되어서 상당히 비효율적이 됩니다.&lt;br /&gt;이런 이유도 포인터를 사용하는 이유중 하나입니다.&lt;/li&gt;
&lt;li&gt;call-by-reference 방식&lt;br /&gt;print_reference(&amp;amp;currentPrice_st);&lt;br /&gt;변수에 대한 주소는 변수앞에&lt;b&gt; &amp;amp;&lt;/b&gt; 를 붙여서 만든다고 설명드렸지요. 그래서 여기서도 &amp;amp;currentPrice_st로 파라메타를 넘겨줍니다.&lt;br /&gt;출력에서 알수 있듯이 currentPrice_st 주소와 print_reference() 주소가 같은걸 알수 있습니다.&lt;br /&gt;call-by-value 방식과 다르게 call-by-reference에서는 구조체 크기 만큼 메모리 할당이 일어나지 않습니다.&lt;br /&gt;currentPrice_st의 메모리를 포인터로 바로 사용하기 때문입니다.&lt;br /&gt;이때 구조체 멤버를 접근할때는&lt;b&gt; -&amp;gt;&lt;/b&gt; 를 사용합니다.&lt;/li&gt;
&lt;li&gt;구조체의 멤버 접근은 &lt;b&gt;구조체 변수명 . 멤버명&lt;/b&gt;이고&lt;br /&gt;구조체의 포인터 멤버 접근은 &lt;b&gt;구조체 변수명-&amp;gt;멤버명&lt;/b&gt; 입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-4) 함수 예제 프로그램2&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct7.c&lt;/p&gt;
&lt;pre id=&quot;code_1669011143878&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

#pragma pack(1)

// 주식 현재가 struct 의 새로운 타입을 정의
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
} CURRENT_PRICE_ST;

// call-by-value로 구조체 사용하기
void print_value(CURRENT_PRICE_ST valuePrice) {
    printf(&quot;--- print_value(%p) ---\n&quot;, &amp;amp;valuePrice);       // 메모리주소 출력
    printf(&quot;주식코드:[%s]\n&quot;, valuePrice.code);
    printf(&quot;주식명  :[%s]\n&quot;, valuePrice.name);
    printf(&quot;현재가  :[%d]\n&quot;, valuePrice.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, valuePrice.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, valuePrice.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, valuePrice.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, valuePrice.qty);
}

// call-by-reference로 구조체 사용하기
void print_reference(CURRENT_PRICE_ST *ptrPrice) {
    printf(&quot;--- print_reference(%p) ---\n&quot;, ptrPrice);  // 메모리주소 출력
    printf(&quot;주식코드:[%s]\n&quot;, ptrPrice-&amp;gt;code);
    printf(&quot;주식명  :[%s]\n&quot;, ptrPrice-&amp;gt;name);
    printf(&quot;현재가  :[%d]\n&quot;, ptrPrice-&amp;gt;currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, ptrPrice-&amp;gt;startPrice);
    printf(&quot;고가    :[%d]\n&quot;, ptrPrice-&amp;gt;highPrice);
    printf(&quot;저가    :[%d]\n&quot;, ptrPrice-&amp;gt;lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, ptrPrice-&amp;gt;qty);
}

void main() {
    // struct _tagCurrentPrice의 선언
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};
    // 포인터 변수
    CURRENT_PRICE_ST *ptrPrice_st = &amp;amp;currentPrice_st;

    // currentPrice_st 크기와 메모리 주소 출력
    printf(&quot;currentPrice_st 주소[%p]\n&quot;, &amp;amp;currentPrice_st);
    printf(&quot;    ptrPrice_st 주소[%p]\n&quot;, ptrPrice_st);

    // call-by-value 값 출력
    print_value(currentPrice_st);

    // call-by-reference 값 출력
    print_reference(ptrPrice_st);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669011174026&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct7 struct7.c
~/c-lecture (master ✘)✭ ᐅ ./struct7
currentPrice_st 주소[0x7ffe4f50e980]
    ptrPrice_st 주소[0x7ffe4f50e980]
--- print_value(0x7ffe4f50e8f0) ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
--- print_reference(0x7ffe4f50e980) ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 포인터 변수를 선언과 동시에 버퍼 주소를 할당합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1669011259809&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    // 포인터 변수
    CURRENT_PRICE_ST *ptrPrice_st = &amp;amp;currentPrice_st;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 강의에서 설명드렸는데 &lt;b&gt;포인터 변수는 단독(버퍼없이)으로는 사용할 수 없다&lt;/b&gt;고 말씀드렸습니다.&lt;br /&gt;ptrPrice_st = &amp;amp;currentPrice_st; 로 currentPrice_st의 주소를 ptrPrice_st에 할당합니다.&lt;br /&gt;그래서 여기서는 currentPrice_st가 포인터변수의 버퍼입니다. 114바이트 크기의 버퍼.&lt;/li&gt;
&lt;li&gt;출력을 보시면 ptrPrice_st값이 같은걸 알 수 있습니다.&lt;/li&gt;
&lt;li&gt;포인터의 중요한 개념이므로 다시 한번 강조해서 설명드립니다.&lt;br /&gt;&lt;b&gt;포인터 변수는 항상 버퍼의 주소를 할당 받아서 사용합니다. 단독으로는 사용하실 수 없습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>Call-By-Reference</category>
      <category>Call-by-value</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>struct</category>
      <category>리눅스</category>
      <category>포인터</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/23</guid>
      <comments>https://dayudev.tistory.com/23#entry23comment</comments>
      <pubDate>Mon, 21 Nov 2022 15:19:15 +0900</pubDate>
    </item>
    <item>
      <title>16. 구조체(struct)</title>
      <link>https://dayudev.tistory.com/22</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체(struct) 이해하기&lt;/li&gt;
&lt;li&gt;구조체 사용법 이해하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체는 여러 타입을 묶어서 사용하는 자료구조형입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668988272808&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// struct 정의
struct tag {
    char member1;
    int member2;
    double member3;
};

// struct 선언
struct tag myTag;

// typedef를 사용한 struct 정의
// MY_TAG를 새로운 타입으로 생성
typedef struct {
    char member1;
    int member2;
    double member3;
} MY_TAG;

// struct 선언
MY_TAG myTag;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체의 정의는&amp;nbsp;&lt;br /&gt;struct (키워드) tag(태그명) { 사용하고자 하는 타입들 };&lt;br /&gt;태그명은 여러분들이 알맞은 이름을 사용하시면 됩니다.&amp;nbsp;&lt;br /&gt;주식의 현재를 예를 들면 주식의 코드, 주식명, 현재가, 시가, 고가, 저가, 거래량 으로 정의 될수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668990715197&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 주식의 현재가
struct _tagCurrentPrice {
    char code[10];     // 주식코드
    char name[80];     // 주식명
    int currentPrice;  // 현재가
    int startPrice;    // 시가
    int highPrice;     // 고가
    int lowPrice;      // 저가
    double qty;        // 거래량
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;태그명은 _tagCurrentPrice로 지정했고, 현재가라는 구조체가 관리(처리)하는 데이타는 code, name, currentPrice, startPrice, highPrice, lowPrice, qty 라는 멤버로 정의 합니다.&lt;/li&gt;
&lt;li&gt;현재가 구조체를 사용하고자 하면&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668990900914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct _tagCurrentPrice CurrentPrice_st;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 선언을 해서 사용합니다. c언어에서 제공하는 타입을 선언할때 타입 변수명; 으로 선언을 했듯이 구조체도 struct _tagCurrentPrice 타입으로 CurrentPrice_st라는 변수명으로 선언을 합니다.&lt;br /&gt;&lt;b&gt;※ 선언을 할때만 메모리에 할당이 됩니다. 위에서 현재가 구조체를 정의할때는 메모리에 할당되지 않습니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;현재가 구조체의 멤버 (code, name, currentPrice, startPrice, highPrice, lowPrice, qty)에 접근할때는&lt;br /&gt;CurrentPrice_st.code, CurrentPrice_st.name, CurrentPrice_st.currentPrice, &lt;span&gt;CurrentPrice_st.startPrice,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;CurrentPrice_st.highPrice, CurrentPrice_st.lowPrice, CurrentPrice_st.qty 로 &lt;br /&gt;&lt;b&gt;구조체 변수명에 . 를 붙이고 멤버명을 써 주시면 해당하는 멤버에 접근 할 수 있습니다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct.c&lt;/p&gt;
&lt;pre id=&quot;code_1669003521947&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

// 주식 현재가 struct 정의
struct _tagCurrentPrice {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
};

void main() {
    // struct _tagCurrentPrice의 선언
    struct _tagCurrentPrice currentPrice_st;

    // 멤버 주식코드 값을 설정
    memset(currentPrice_st.code, 0x00, sizeof(currentPrice_st.code));
    strcpy(currentPrice_st.code, &quot;A005930&quot;);

    // 멤버 주식명 값을 설정
    memset(currentPrice_st.name, 0x00, sizeof(currentPrice_st.name));
    strcpy(currentPrice_st.name, &quot;삼성전자&quot;);

    // 멤버 현재가 값을 설정
    currentPrice_st.currentPrice = 61000;

    // 멤버 시가 값을 설정
    currentPrice_st.startPrice = 60500;

    // 멤버 고가 값을 설정
    currentPrice_st.highPrice = 62000;

    // 멤버 저가 값을 설정
    currentPrice_st.lowPrice = 60300;

    // 멤버 거래량 값을 설정
    currentPrice_st.qty = 1234500.0;

    // 값 출력
    printf(&quot;주식코드:[%s]\n&quot;, currentPrice_st.code);
    printf(&quot;주식명  :[%s]\n&quot;, currentPrice_st.name);
    printf(&quot;현재가  :[%d]\n&quot;, currentPrice_st.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, currentPrice_st.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, currentPrice_st.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, currentPrice_st.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, currentPrice_st.qty);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669003619187&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct struct.c
~/c-lecture (master ✘)✭ ᐅ ./struct
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구조체를 struct _tagCurrentPrice 로 정의를 했고, struct _tagCurrentPrice currentPrice_st 로 선언을 했습니다.&lt;/li&gt;
&lt;li&gt;구조체의 멤버에 값을 할당합니다.&lt;br /&gt;char code[10], char name[80] 은 문자열로 값을 할당하는데 memset()로 초기화를 하고 strcpy()를 사용을 해서 값을 설정합니다.&lt;br /&gt;strcpy(currentPrice_st.code,&amp;nbsp;&quot;A005930&quot;);&lt;br /&gt;strcpy(currentPrice_st.name,&amp;nbsp;&quot;삼성전자&quot;);&lt;br /&gt;struct 변수 . 멤버이름으로 접근합니다.&lt;/li&gt;
&lt;li&gt;struct도 선언과 동시에 초기값을 설정할 수 있습니다.&lt;br /&gt;struct _tagCurrentPrice currentPrice_st = &lt;b&gt;{&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0}&lt;/b&gt;;&lt;/li&gt;
&lt;li&gt;printf()함수로 멤버를 출력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2)&amp;nbsp; 값대입 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct2.c&lt;/p&gt;
&lt;pre id=&quot;code_1669005591198&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

// 주식 현재가 struct 정의
struct _tagCurrentPrice {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
};

void main() {
    // struct _tagCurrentPrice의 선언
    struct _tagCurrentPrice currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};
    struct _tagCurrentPrice tmpPrice_st;

    // 값 출력
    printf(&quot;--- currentPrice_st 출력 ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, currentPrice_st.code);
    printf(&quot;주식명  :[%s]\n&quot;, currentPrice_st.name);
    printf(&quot;현재가  :[%d]\n&quot;, currentPrice_st.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, currentPrice_st.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, currentPrice_st.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, currentPrice_st.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, currentPrice_st.qty);

    // struct 값 대입
    tmpPrice_st = currentPrice_st;

    printf(&quot;--- tmpPrice_st 출력 ---\n&quot;);
    printf(&quot;주식코드:[%s]\n&quot;, tmpPrice_st.code);
    printf(&quot;주식명  :[%s]\n&quot;, tmpPrice_st.name);
    printf(&quot;현재가  :[%d]\n&quot;, tmpPrice_st.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, tmpPrice_st.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, tmpPrice_st.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, tmpPrice_st.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, tmpPrice_st.qty);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669005626258&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct2 struct2.c
~/c-lecture (master ✘)✭ ᐅ ./struct2
--- currentPrice_st 출력 ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
--- tmpPrice_st 출력 ---
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&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&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;currentPrice_st 선언과 동시에 값을 할당합니다.&lt;br /&gt;struct&amp;nbsp;_tagCurrentPrice&amp;nbsp;currentPrice_st&amp;nbsp;=&amp;nbsp;{&quot;A005930&quot;,&amp;nbsp;&quot;삼성전자&quot;,&amp;nbsp;61000,&amp;nbsp;60500,&amp;nbsp;62000,&amp;nbsp;60300,&amp;nbsp;1234500.0};&lt;/li&gt;
&lt;li&gt;struct _tagCurrentPrice 의 다른 변수 tmpPrice_st를 선언합니다.&lt;/li&gt;
&lt;li&gt;같은 struct인 경우 = 대입 연산자로 값을 할당할 수 있습니다.&lt;br /&gt;tmpPrice_st&amp;nbsp;=&amp;nbsp;currentPrice_st;&lt;/li&gt;
&lt;li&gt;출력을 보면 값이 같은걸 확인하실 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) typedef문 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi struct3.c&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669004354690&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

// 주식 현재가 struct 의 새로운 타입을 정의
typedef struct {
    char code[10];          // 주식코드
    char name[80];          // 주식명
    int currentPrice;       // 현재가
    int startPrice;         // 시가
    int highPrice;          // 고가
    int lowPrice;           // 저가
    double qty;             // 거래량
} CURRENT_PRICE_ST;

void main() {
    // struct _tagCurrentPrice의 선언
    CURRENT_PRICE_ST currentPrice_st = {&quot;A005930&quot;, &quot;삼성전자&quot;, 61000, 60500, 62000, 60300, 1234500.0};

    // 값 출력
    printf(&quot;주식코드:[%s]\n&quot;, currentPrice_st.code);
    printf(&quot;주식명  :[%s]\n&quot;, currentPrice_st.name);
    printf(&quot;현재가  :[%d]\n&quot;, currentPrice_st.currentPrice);
    printf(&quot;시가    :[%d]\n&quot;, currentPrice_st.startPrice);
    printf(&quot;고가    :[%d]\n&quot;, currentPrice_st.highPrice);
    printf(&quot;저가    :[%d]\n&quot;, currentPrice_st.lowPrice);
    printf(&quot;거래량  :[%.0f]\n&quot;, currentPrice_st.qty);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1669004382640&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o struct2 struct2.c
~/c-lecture (master ✘)✭ ᐅ ./struct2
주식코드:[A005930]
주식명  :[삼성전자]
현재가  :[61000]
시가    :[60500]
고가    :[62000]
저가    :[60300]
거래량  :[1234500]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;typedef 문을 사용해서 struct 태그명을 사용하기 쉬운 별칭으로 정의할 수 있습니다.&lt;br /&gt;struct _tagCurrentPrice 를 typedef struct ~~ CURRENT_PRICE_ST 로 별칭을 새롭게 정의하였습니다.&lt;br /&gt;구조체를 선언할때 이 별칭으로 사용됩니다.&lt;br /&gt;CURRENT_PRICE_ST currentPrice_st;&lt;br /&gt;struct _tagCurrentPrice로 사용할때 보다 간결하게 사용가능합니다.&lt;br /&gt;보통 개발할때 구조체는 typedef로 별칭을 새롭게 정의해서 사용합니다.&lt;/li&gt;
&lt;li&gt;선언과 동시에 초기값을 설정해 보았습니다.&lt;br /&gt;CURRENT_PRICE_ST&amp;nbsp;currentPrice_st&amp;nbsp;=&amp;nbsp;{&quot;A005930&quot;,&amp;nbsp;&quot;삼성전자&quot;,&amp;nbsp;61000,&amp;nbsp;60500,&amp;nbsp;62000,&amp;nbsp;60300,&amp;nbsp;1234500.0};&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>Member</category>
      <category>struct</category>
      <category>리눅스</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/22</guid>
      <comments>https://dayudev.tistory.com/22#entry22comment</comments>
      <pubDate>Mon, 21 Nov 2022 13:26:33 +0900</pubDate>
    </item>
    <item>
      <title>15. 문자열(배열) 다루기</title>
      <link>https://dayudev.tistory.com/21</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열(배열)을 다루는 함수 알아보기&lt;/li&gt;
&lt;li&gt;문자열(배열) 함수 사용해 보기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제목처럼 문자열(배열) 다루는 것은 사실 메모리를 다루는 기술입니다.&lt;br /&gt;변수를 선언하면 메모리가 할당이 되고 변수에 값을 넣고 참조할 수 있는것이 메모리를 다루는것 입니다.&lt;/li&gt;
&lt;li&gt;여기서는 c언어에서 제공하는 문자열 관련 함수, 메모리 관련 함수를 다루고자 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) 메모리 관련 함수 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi mem.c&lt;/p&gt;
&lt;pre id=&quot;code_1668659680269&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

void main() {
    char str[] = &quot;Hello, World&quot;;
    char buf[12];

    // str의 내용을 buf로 복사함
    memcpy(buf, str, 12);               // Hello, World (12자)

    printf(&quot;buf:[%12.12s]\n&quot;, buf);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668659971860&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o mem mem.c
~/c-lecture (master ✘)✭ ᐅ ./mem
buf:[Hello, World]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 살펴볼 함수는 상당히 많이 쓰이는 memcpy()함수 입니다.&lt;br /&gt;이 함수를 사용하기 위해서 #include &amp;lt;string.h&amp;gt; 문이 추가됩니다.&lt;br /&gt;man memcpy 로 확인해 보시면 아래와 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;942&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b62vFf/btrRrovaLgi/2gWhk6bFJEb8lVNqOMwlA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b62vFf/btrRrovaLgi/2gWhk6bFJEb8lVNqOMwlA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b62vFf/btrRrovaLgi/2gWhk6bFJEb8lVNqOMwlA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb62vFf%2FbtrRrovaLgi%2F2gWhk6bFJEb8lVNqOMwlA1%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;600&quot; height=&quot;942&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;942&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수의 프로토타입도 자세히 나와 있습니다.&lt;br /&gt;&lt;b&gt;void *memcpy(void *dest, const void *src, size_t n);&lt;/b&gt;&lt;br /&gt;간략하게 설명을 드리면 두번째 인자 src에서 첫번째 인자 dest로 세번째 인자 크기 n 만큼 복사하는 함수 입니다.&lt;br /&gt;※ void * 가 나오는데 void 포인터형입니다. 이 void 포인터형은 어떠한 타입으로도 될 수 있다는 의미입니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp;예제 mem.c에서는 char 타입을 넘겨주는데 memcpy 함수가 void 타입으로 받아서 가능합니다.&lt;br /&gt;※ size_t 은 정수형으로 크기를 나타내고 있다는 정도로만 알아두세요.&lt;br /&gt;※ 두번째 인자를 보시면 앞에 const가 붙은걸 알수 있습니다. &lt;b&gt;const 의미는 상수&lt;/b&gt;의 의미가 있습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 변수와 다르게 &lt;b&gt;상수는 값을 변경할 수 없습니다.&lt;/b&gt; &lt;br /&gt;&amp;nbsp; &amp;nbsp; 그래서 memcpy()함수내에서 src의 내용은 변경할 수 없다는걸 정의하고 있습니다.&lt;/li&gt;
&lt;li&gt;memcpy()함수를 사용하면 for문으로 반복처리를 할 필요가 없습니다.&lt;/li&gt;
&lt;li&gt;'Hello, World'의 문자수는 12자 즉, 12바이트를 차지합니다. 그래서 복사할 대상를 char buf[12];로 선언을 하고&lt;br /&gt;memcpy(buf, str, 12); 변수 str의 값을 buf로 12바이트 복사하는 것입니다.&lt;/li&gt;
&lt;li&gt;buf를 출력할때 printf의 서식 &lt;b&gt;%12.12s&lt;/b&gt; 를 사용했는데요. 이 서식은 %s 문자열 출력 서식과 유사합니다.&lt;br /&gt;소수점(.)를 기준으로 앞의 12는 전체자리수 뒤의 12는 출력할 변수(buf)의 자리수를 의미합니다.&lt;br /&gt;즉, buf[12] 12바이트를 출력하고자 %12.12s 의 서식을 사용했습니다.&lt;br /&gt;printf()함수의 서식은 상당히 많이 있습니다. 필자도 전부 외우지 못합니다. 여러분도 이런 서식이 있구나. 라고 인지만 하시고 나중에 필요할때 man 3 printf 라던가 구글에서 검색해서 사용하시면 됩니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;문자열에서 설명드렸는데요. 예제의 char buf[12]; 은 문자열(string)이 아닙니다.&lt;br /&gt;문자열은 마지막에 null(0x00) 문자가 있어야 문자열이 된다고 말씀을 드렸죠.&lt;br /&gt;문자열이 아니기 때문에 printf()에서도 %s가 아닌 %12.12s로 출력한 것입니다.&lt;br /&gt;(%s 서식은 출력할 변수에서 null문자까지 출력합니다.)&lt;br /&gt;그럼 buf를 문자열로 바꿀려면 어떻게 하면 되나요? 그렇죠 마지막에 null(0x00)를 추가하면 되겠죠.&lt;br /&gt;그런데 memcpy()함수를 사용하는데 마지막에 null(0x00)를 추가하는게 쉽지가 않습니다. &lt;br /&gt;buf의 마지막 위치를 알아야 하지요. 이때 이런 문제를 해결할수 있는 함수가 존재합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) 메모리 관련 함수 예제 프로그램 2&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi mem2.c&lt;/p&gt;
&lt;pre id=&quot;code_1668661619459&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

void main() {
    char str[] = &quot;Hello, World&quot;;
    char buf[32];                       // 버퍼 크기를 12 -&amp;gt; 32로 넉넉히 잡습니다.

    // buf를 null 문자로 초기화 합니다.
    memset(buf, 0x00, sizeof(buf));

    // str의 내용을 buf로 복사함
    memcpy(buf, str, 12);               // Hello, World (12자)

    printf(&quot;buf:[%s]\n&quot;, buf);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668661650767&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o mem2 mem2.c
~/c-lecture (master ✘)✭ ᐅ ./mem2
buf:[Hello, World]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;buf를 문자열(string)로 만드는게 목표입니다.&lt;br /&gt;여기서 memset() 함수가 새로게 등장합니다. 이함수도 memcpy와 같이 상당히 많이 쓰입니다.&lt;br /&gt;memcpy()함수를 사용할때 한짝으로 memset()가 자주 사용됩니다.&lt;br /&gt;memset도 자세히 알고 싶으시면 man memset 으로 보시면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY4zi7/btrRoq8OQw6/DJTAFMwWfQWoTuYLdNglVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY4zi7/btrRoq8OQw6/DJTAFMwWfQWoTuYLdNglVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY4zi7/btrRoq8OQw6/DJTAFMwWfQWoTuYLdNglVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY4zi7%2FbtrRoq8OQw6%2FDJTAFMwWfQWoTuYLdNglVk%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;600&quot; height=&quot;944&quot; data-origin-width=&quot;1534&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;memset함수의 프로토타입을 보면&lt;br /&gt;&lt;b&gt;void *memset(void *s, int c, size_t n);&lt;/b&gt;&lt;br /&gt;첫번째 인자 s를 두번째 인자 c로 세번째 인자 n만큼 채우라는 의미 입니다.&lt;br /&gt;memset(buf, 'A', 10); 의 의미는 buf값을 'A'로 10개 채우라는 의미입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668662097494&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    // buf를 null 문자로 초기화 합니다.
    memset(buf, 0x00, sizeof(buf));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변수 buf의 값을 null(0x00)으로 채우라는 의미입니다. 여기서 sizeof(buf) 가 나오는데요&lt;br /&gt;4.변수 강의에서 설명드렸는데요. sizeof()는 변수타입뿐 아니라 이렇게 배열의 크기를 구하는데도 사용됩니다.&lt;br /&gt;sizeof() 는 상당히 많이 사용됩니다. 이렇게 사용되는것도 알아두세요.&lt;br /&gt;그래서 sizeof(buf) == 32입니다. char buf[32]; 로 선언되었기 때문에 32입니다.&lt;/li&gt;
&lt;li&gt;buf 배열은 크기가 32바이트이고 그값은 전부 null로 되어있게 됩니다.&lt;/li&gt;
&lt;li&gt;여기에 memcpy()문으로 str값 12바이트를 복사하게 되면&lt;br /&gt;buf의 처음 12바이트는 'Hello World'가 되고 나머지는 null(0x00)로 그대로 있습니다.&lt;br /&gt;그러면 buf는 문자열인가요? 맞습니다 원하는 데이타 마지막에 null(0x00)문자가 있기 때문에 문자열입니다.&lt;/li&gt;
&lt;li&gt;buf 문자열을 출력하기 위해서 printf()의 서식을 %s 만을 사용해서 출력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) 문자열 관련 함수 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi str.c&lt;/p&gt;
&lt;pre id=&quot;code_1668662869568&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

void main() {
    char str[] = &quot;Hello, World&quot;;
    char buf[32];

    // str의 내용을 buf로 복사함
    strcpy(buf, str);

    printf(&quot;buf:[%s]\n&quot;, buf);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668662901852&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o str str.c
~/c-lecture (master ✘)✭ ᐅ ./str
buf:[Hello, World]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이번 예제는 문자열을 다룹니다.&lt;br /&gt;char str[] = &quot;Hello World&quot;; 이전 강의에서 설명드렸는데 &lt;br /&gt;배열을 선언과 동시에 문자열로 초기화 가능합니다. str은 문자열입니다.&lt;/li&gt;
&lt;li&gt;이번 예제에서는 strcpy()함수가 나옵니다. memcpy()함수와 마찬가지로 많이 쓰이는 함수입니다.&lt;br /&gt;man strcpy 로 보시면 프로토타입등 상세한 설명을 보실 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1533&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBGypU/btrRs9LbigM/7ODmjLw1BQ6sCkISG4r9BK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBGypU/btrRs9LbigM/7ODmjLw1BQ6sCkISG4r9BK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBGypU/btrRs9LbigM/7ODmjLw1BQ6sCkISG4r9BK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBGypU%2FbtrRs9LbigM%2F7ODmjLw1BQ6sCkISG4r9BK%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;600&quot; height=&quot;940&quot; data-origin-width=&quot;1533&quot; data-origin-height=&quot;940&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입을 보면&lt;br /&gt;&lt;b&gt;char *strcpy(char *dest, const char *src);&lt;/b&gt;&lt;br /&gt;두번째 인자 src를 첫번째 인자 dest로 복사하는 함수입니다. 주의할점은 src는 문자열이어야 합니다.&lt;br /&gt;src의 값에서 null(0x00)일때 까지 dest로 복사합니다. 만약 src가 문자열이 아닌 경우 문제가 발생할 수 있습니다.&lt;br /&gt;그러니 문자열의 개념은 반드시 알아두셔야 합니다. 반드시 null(0x00)값을 끝나야 합니다.&lt;br /&gt;&lt;b&gt;첫번째 인자 dest의 크기는 src보다 반드시 크거나 같아야 합니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;strcpy()함수를 사용하면 복사된 변수도 문자열이 됩니다.&lt;br /&gt;printf()함수에서 %s 서식으로 출력 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-4) 문자열 관련 함수 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi str2.c&lt;/p&gt;
&lt;pre id=&quot;code_1668663810574&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

void main() {
    char str[] = &quot;Hello, World&quot;;
    char buf[32];
    int len;

    // str의 내용을 buf로 복사함
    strcpy(buf, str);

    // 문자열의 크기를 구하는 함수
    len = strlen(buf);

    printf(&quot;buf:[%s] 길이:[%d]\n&quot;, buf, len);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668663867463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o str2 str2.c
~/c-lecture (master ✘)✭ ᐅ ./str2
buf:[Hello, World] 길이:[12]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 함수중 많이 사용하는 strlen()함수를 알아보겠습니다.&lt;br /&gt;함수 이름에서 알수 있듯이 문자열의 길이(크기)를 구하는 함수입니다.&lt;br /&gt;문자열의 길이는 null문자가 제외된 길이입니다.&lt;br /&gt;man strlen 으로 보시면 좀 더 상세히 보실 수 있습니다.&lt;/li&gt;
&lt;li&gt;strcpy()와 같이 strlen()함수도 알아 두세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 개발을 하다 보면 memcpy(), strcpy() 등 관련된 함수가 상당히 많이 사용됩니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 강의를 진행하면서 언제 어떻게 사용되는 자세히 알아 보도록 하겠습니다.&lt;br /&gt;※ 이번 강의에서는 memcpy(), strcpy()함수 함께 문자열을 개념을 다시 한번 잘 이해하시기 바랍니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 상당히 중요한 개념입니다.&lt;/p&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>memcpy</category>
      <category>memset</category>
      <category>strcpy</category>
      <category>String</category>
      <category>strlen</category>
      <category>리눅스</category>
      <category>문자열</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/21</guid>
      <comments>https://dayudev.tistory.com/21#entry21comment</comments>
      <pubDate>Thu, 17 Nov 2022 11:06:14 +0900</pubDate>
    </item>
    <item>
      <title>14. 함수 파라메타 유형</title>
      <link>https://dayudev.tistory.com/20</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp; &amp;nbsp; ▶함수 파라메타 유형에 대해서 알아보기&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;call-by-value 이해하기.&lt;/li&gt;
&lt;li&gt;call-by-reference 이해하기.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수에 넘겨주는 파라메타(인자값)의 유형은 &lt;br /&gt;값을 넘겨 주는 방식(call-by-value),&lt;br /&gt;주소(포인터)를 넘겨 주는 방식(call-by-reference)이 있습니다.&lt;/li&gt;
&lt;li&gt;call-by-value 방식은 함수를 부르는쪽이나 함수나 서로 영향을 주기 않습니다.&lt;br /&gt;14.함수에서 살펴본 sum(int a, int b) 함수가 call-by-value의 전형적인 함수입니다.&lt;/li&gt;
&lt;li&gt;call-by-reference 방식은 주소를 넘겨 주고, 넘겨 받아서 처리하기에 값에 영향을 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) call-by-value 방식 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi func3.c&lt;/p&gt;
&lt;pre id=&quot;code_1668642858421&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// val1값과 val2값을 바꾸는 swap함수

// call-by-value 방식
void swap_value(int val1, int val2) {
    int tmp;

    printf(&quot;swap_value: swap전 val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);

    // tmp를 이용한 val1 &amp;lt;-&amp;gt; val2
    tmp = val1;
    val1 = val2;
    val2 = tmp;

    printf(&quot;swap_value: swap후 val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);
}

// swap함수
void main() {
    int val1, val2;

    val1 = 100;
    val2 = 200;

    printf(&quot;main: swap_value() 호출전 : val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);

    // call-by-value 방식
    swap_value(val1, val2);

    printf(&quot;main: swap_value() 호출후 : val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668642899387&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func3 func3.c
~/c-lecture (master ✘)✭ ᐅ ./func3
main: swap_value() 호출전 : val1[100][0x7ffc1fbbb670] val2[200][0x7ffc1fbbb674]
swap_value: swap전 val1[100][0x7ffc1fbbb64c] val2[200][0x7ffc1fbbb648]
swap_value: swap후 val1[200][0x7ffc1fbbb64c] val2[100][0x7ffc1fbbb648]
main: swap_value() 호출후 : val1[100][0x7ffc1fbbb670] val2[200][0x7ffc1fbbb674]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;swap함수내에서는 swap전, swap후의 값을 보면 val1값과 val2값이 바뀌어 있는걸 보실 수 있습니다.&lt;br /&gt;그런데 main()내에서는 swap() 호출전이나 호출후의 값을 보면 그대로 인걸 알수 있습니다.&lt;br /&gt;이렇듯 call-by-value방식은 호출하는쪽의 변수값을 바꾸질 못합니다.&lt;br /&gt;이유는 main()함수내에서 int val1, val2; 선언시 메모리가 할당이 되고 swap_value()함수를 호출을 하면&lt;br /&gt;swap_value()함수에서 파라메타에 대해서 새로운 메모리가 할당이 됩니다.&lt;br /&gt;그래서 swap_value()함수내에서 작업하는 곳은 새롭게 할당된 메모리가 되어서 main()함수에서 할당받은&amp;nbsp;&lt;br /&gt;메모리에 여향을 주지 못합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668643838560&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf(&quot;main: swap_value() 호출전 : val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선언한 변수에 대해서 메모리 주소를 알아 보기 위해서 이전 강의에서 배운 %p를 사용했습니다.&lt;br /&gt;또한 %p 에 대한 값으로는 변수에 대한 주소를 사용하기 위해서 변수앞에 &amp;amp; 를 붙여서 사용합니다.&lt;br /&gt;위의 결과를 보시면 main()함수에서 val1주소, val2주소가 swap_value()함수에서는 전혀 다른 주소가 출력된걸 확인하실 수 있습니다.&lt;/li&gt;
&lt;li&gt;main()에서 선언한 val1, val2값을 바꾸기 위해서는 어떻게 해야할까요?&lt;br /&gt;해답은 이전 강의에서 배운 포인터가 사용됩니다. 알아볼까요?&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) call-by-reference 방식 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ vi func4.c&lt;/p&gt;
&lt;pre id=&quot;code_1668644242905&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// val1값과 val2값을 바꾸는 swap함수

// call-by-reference 방식
void swap_reference(int *pVal1, int *pVal2) {
    int tmp;

    printf(&quot;swap_reference: swap전 val1[%d][%p] val2[%d][%p]\n&quot;, *pVal1, pVal1, *pVal2, pVal2);

    // tmp를 이용한 val1 &amp;lt;-&amp;gt; val2
    tmp = *pVal1;
    *pVal1 = *pVal2;
    *pVal2 = tmp;

    printf(&quot;swap_reference: swap후 val1[%d][%p] val2[%d][%p]\n&quot;, *pVal1, pVal1, *pVal2, pVal2);
}

// swap함수
void main() {
    int val1, val2;

    val1 = 100;
    val2 = 200;

    printf(&quot;main: swap_reference() 호출전 : val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);

    // call-by-reference 방식
    swap_reference(&amp;amp;val1, &amp;amp;val2);

    printf(&quot;main: swap_reference() 호출후 : val1[%d][%p] val2[%d][%p]\n&quot;, val1, &amp;amp;val1, val2, &amp;amp;val2);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668644271311&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func4 func4.c
~/c-lecture (master ✘)✭ ᐅ ./func4
main: swap_reference() 호출전 : val1[100][0x7ffced6b8ae0] val2[200][0x7ffced6b8ae4]
swap_reference: swap전 val1[100][0x7ffced6b8ae0] val2[200][0x7ffced6b8ae4]
swap_reference: swap후 val1[200][0x7ffced6b8ae0] val2[100][0x7ffced6b8ae4]
main: swap_reference() 호출후 : val1[200][0x7ffced6b8ae0] val2[100][0x7ffced6b8ae4]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행한 결과를 보시면 main() 내 val1, val2값이 swap_reference() 호출후에 바뀌어 있는걸 확인하실 수 있습니다.&lt;br /&gt;또한 main()함수내 val1, val2주소가 swap_reference()함수내에서도 같은걸 보실 수 있습니다.&lt;br /&gt;이렇듯 같은 메모리 주소를 사용하므로 변수에 영향을 줄 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668644476255&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    // call-by-reference 방식
    swap_reference(&amp;amp;val1, &amp;amp;val2);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 호출할때 변수에 대한 주소를 넘겨주기 위해서 변수명 앞에 &amp;amp; 를 붙여서 넘겨 주고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668644546799&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
// call-by-reference 방식
void swap_reference(int *pVal1, int *pVal2) {&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;호출된 함수에서도 파라메타가 주소, 즉 포인터이므로 포인터 형으로 정의가 되어 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) call-by-reference 배열 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ vi func5.c&lt;/p&gt;
&lt;pre id=&quot;code_1668645225101&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// 배열값 hello를 world로 바꾸는 함수

// call-by-reference 방식
void array_reference(char *pStr) {
    char new_str[] = &quot;world&quot;;
    int i;

    printf(&quot;array_reference: swap전 [%s][%p]\n&quot;, pStr, pStr);

    for (i = 0; i &amp;lt; 6; i++) {
        // new_str:world로 대체
        *(pStr + i) = new_str[i];
    }

    printf(&quot;array_reference: swap후 [%s][%p]\n&quot;, pStr, pStr);
}

// swap함수
void main() {
    char str[] = &quot;hello&quot;;

    printf(&quot;main: array_reference() 호출전 : str[%s][%p]\n&quot;, str, str);

    // call-by-reference 방식
    array_reference(str);

    printf(&quot;main: array_reference() 호출후 : str[%s][%p]\n&quot;, str, str);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668645253019&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func5 func5.c
~/c-lecture (master ✘)✭ ᐅ ./func5
main: array_reference() 호출전 : str[hello][0x7fff674cba82]
array_reference: swap전 [hello][0x7fff674cba82]
array_reference: swap후 [world][0x7fff674cba82]
main: array_reference() 호출후 : str[world][0x7fff674cba82]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;main()함수의 str='hello'를 array_reference()에서 'world'로 바꾸는 프로그램입니다.&lt;/li&gt;
&lt;li&gt;결과를 보시면 main() 에서 호출전은 'hello', 호출후에는 'world'로 바뀌어 있는걸 확인 하실 수 있습니다.&lt;br /&gt;물론 str의 주소와 array_reference()내에서의 주소도 동일합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668645406573&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
    // call-by-reference 방식
    array_reference(str);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 강의에서도 설명한대로 배열은 배열 이름 자체가 주소가 됩니다. 그래서 array_reference 호출시 배열변수명 str이 그대로 사용되었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668645514268&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
// call-by-reference 방식
void array_reference(char *pStr) {&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 파라메타에서도 포인터형으로 정의되어 있습니다.&lt;/li&gt;
&lt;li&gt;call-by-reference 방식은 c프로그램에서 상당히 많이 사용하는 방식입니다.&lt;br /&gt;함수호출 방식과 호출된 함수의 파라메타 정의에 대해서 이해하시기 바랍니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>Call-By-Reference</category>
      <category>Call-by-value</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>리눅스</category>
      <category>파라메타</category>
      <category>포인터</category>
      <category>함수</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/20</guid>
      <comments>https://dayudev.tistory.com/20#entry20comment</comments>
      <pubDate>Thu, 17 Nov 2022 08:17:14 +0900</pubDate>
    </item>
    <item>
      <title>14. 함수</title>
      <link>https://dayudev.tistory.com/15</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 이해하기&lt;/li&gt;
&lt;li&gt;함수 리턴값 이해하기&lt;/li&gt;
&lt;li&gt;함수 파라메타 이해하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;pre id=&quot;code_1668494376183&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 함수형식
int func(int arg1) {
	return 0;
}

// 리턴값이 있는 함수
int func() {
	return 0;
}

// 리턴값이 없는 함수
void func() {
}

// 파라메타가 있는 함수
int func(int arg1) {
	return 0;
}

// 파라메타가 여러개 있는 함수
int func(int arg1, int arg2, char arg3) {
	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 함수구성은&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;&lt;i&gt;리턴값타입 함수명(파라메타)&lt;/i&gt;&lt;/b&gt; &lt;b&gt;{ 함수 내용 }&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int func(int argc);&amp;nbsp; &amp;nbsp;리턴타입은&amp;nbsp; int 함수명은 func 파라메타는 int argc 1개로 정의된 함수입니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; int func(); 리턴타입은 int 함수명은 func 파라메타는 없는 함수입니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; void func();&amp;nbsp; 리턴값이 없고 (void) 함수명은 func 파라메타는 없는 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 리턴값이 없는 경우는 &lt;b&gt;void&lt;/b&gt; 로 표기합니다. 참조하세요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 함수의 끝은 return 문을 만나면 끝이나고, 만약 return문이 없다면 함수의 끝을 나타내는 } 를 만나면 끝이 납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 이제는 이런 함수형식으로 내가 원하는 기능을 하는 함수를 만들어서 사용하시면 됩니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) 예제프로그램&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi func.c&lt;/h4&gt;
&lt;pre id=&quot;code_1668583277886&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// 리턴값이 없는 함수
void func1() {
    printf(&quot;func1()...\n&quot;);
}

// 리턴값이 있는 함수
int func2() {
    return 1;
}

// 더하기 함수
int sum(int a, int b) {
    int sum;
    sum = a + b;

    return sum;
}

int main() {
    int ret;

    // 리턴타입이 없는 함수 호출
    func1();

    // 리턴값이 있는 함수 호출
    ret = func2();
    printf(&quot;func2() return value:[%d]\n&quot;, ret);

    // 더하기 함수
    ret = sum(1, 3);
    printf(&quot;sum() return value:[%d]\n&quot;, ret);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668583368899&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func func.c
~/c-lecture (master ✘)✭ ᐅ ./func
func1()...
func2() return value:[1]
sum() return value:[4]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 사용할때는 함수의 타입/파라메타 갯수-형식등을 보고 타입을 맞쳐서 사용하시면 됩니다.&lt;/li&gt;
&lt;li&gt;리턴값이 없는 함수 void func1() 를 사용할때는 func1(); 이렇게 불러서 사용하시면 됩니다.&lt;br /&gt;void func1() 에는 return문이 없습니다. 리턴값타입이 void라서 없습니다. 그런데 함수내에서&amp;nbsp;&lt;br /&gt;return; 문을 추가 할수도 있습니다. 보통은 return 값; 이런 형식으로 사용하는데 void형의 리턴은 값이 없기 때문에 그냥 return; 문으로 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668584141809&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...
void func1() {
	printf(&quot;func1()...\n&quot;);
	return;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리턴값이 있는 함수 int func2() 를 사용할때는 리턴값을 받아서 사용할 수 있으므로&amp;nbsp;&lt;br /&gt;ret = func2(); 이렇게 사용하고 func2()함수에서 리턴해주는 값을 ret를 조회해서 확인합니다.&lt;/li&gt;
&lt;li&gt;리턴값이 있고 파라메타도 int 형으로 2개가 있는 함수 int sum(int a, int b)를 사용할때는&lt;br /&gt;ret = sum(1, 3); 이렇게 사용하고 sum()함수에서 리턴해주는 값은 ret를 조회해서 확인합니다.&lt;/li&gt;
&lt;li&gt;※ c에서는 사용할 함수가 소스 위에 있어야 합니다. 즉, main()함수에서 func1(), func2()를 호출 하는데는 main()함수 보다 먼저 func1(), func2() 함수가 있는걸 보실수 있습니다. 이렇게 사용할 함수가 먼저 나와야 합니다. 아니면 컴파일시 오류가 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) 함수정의 예제프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi func2.c&lt;/p&gt;
&lt;pre id=&quot;code_1668584671568&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    int ret;

    // 리턴타입이 없는 함수 호출
    func1();

    // 리턴값이 있는 함수 호출
    ret = func2();
    printf(&quot;func2() return value:[%d]\n&quot;, ret);

    // 더하기 함수
    ret = sum(1, 3);
    printf(&quot;sum() return value:[%d]\n&quot;, ret);

    return 0;
}

// 리턴값이 없는 함수
void func1() {
    printf(&quot;func1()...\n&quot;);
}

// 리턴값이 있는 함수
int func2() {
    return 1;
}

// 더하기 함수
int sum(int a, int b) {
    int sum;
    sum = a + b;

    return sum;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668584707959&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func2 func2.c
func2.c: In function &amp;lsquo;main&amp;rsquo;:
func2.c:7:2: warning: implicit declaration of function &amp;lsquo;func1&amp;rsquo; [-Wimplicit-function-declaration]
    7 |  func1();
      |  ^~~~~
func2.c:10:8: warning: implicit declaration of function &amp;lsquo;func2&amp;rsquo; [-Wimplicit-function-declaration]
   10 |  ret = func2();
      |        ^~~~~
func2.c:14:8: warning: implicit declaration of function &amp;lsquo;sum&amp;rsquo; [-Wimplicit-function-declaration]
   14 |  ret = sum(1, 3);
      |        ^~~
func2.c: At top level:
func2.c:21:6: warning: conflicting types for &amp;lsquo;func1&amp;rsquo;
   21 | void func1() {
      |      ^~~~~
func2.c:7:2: note: previous implicit declaration of &amp;lsquo;func1&amp;rsquo; was here
    7 |  func1();
      |  ^~~~~
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 사용할 함수의 형식(프로토타입)이 사용하는 위치 보다 선행되어 있어야 합니다.&lt;/li&gt;
&lt;li&gt;지금까지 예제에서 #include &amp;lt;stdio.h&amp;gt; 를 사용하였는데 바로 stdio.h 파일에는 제공하는 함수의 형식(프로토타입)이 정의 되어 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;그럼 오류를 바로 잡아 보겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668585300518&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

// 리턴값이 없는 함수
void func1();
// 리턴값이 있는 함수
int func2();
// 더하기 함수
int sum(int a, int b);

int main() {
    int ret;

    // 리턴타입이 없는 함수 호출
    func1();

    // 리턴값이 있는 함수 호출
    ret = func2();
    printf(&quot;func2() return value:[%d]\n&quot;, ret);

    // 더하기 함수
    ret = sum(1, 3);
    printf(&quot;sum() return value:[%d]\n&quot;, ret);

    return 0;
}

// 리턴값이 없는 함수
void func1() {
    printf(&quot;func1()...\n&quot;);
}

// 리턴값이 있는 함수
int func2() {
    return 1;
}

// 더하기 함수
int sum(int a, int b) {
    int sum;
    sum = a + b;

    return sum;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 사용하는 main()함수 위에 사용할 함수의 형식을 정의합니다.&lt;br /&gt;void&amp;nbsp;func1();&lt;br /&gt;int&amp;nbsp;func2();&lt;br /&gt;int sum(int a, int b);&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668585406501&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o func2 func2.c
~/c-lecture (master ✘)✭ ᐅ ./func2
func1()...
func2() return value:[1]
sum() return value:[4]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정상적으로 컴파일이 되고 실행됩니다.&lt;/li&gt;
&lt;li&gt;c언어에서는 사용할 함수가 먼저 정의되어 있어야 한다. 라고 이해하시면 됩니다.&lt;br /&gt;좀 더 큰 프로그램을 개발할때는 이런 함수의 형식을 모아서 하나의 include파일로 만들어서 사용합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/15</guid>
      <comments>https://dayudev.tistory.com/15#entry15comment</comments>
      <pubDate>Wed, 16 Nov 2022 16:58:42 +0900</pubDate>
    </item>
    <item>
      <title>13. 포인터</title>
      <link>https://dayudev.tistory.com/19</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포인터 개념 이해하기&lt;/li&gt;
&lt;li&gt;이번 강의에서는 포인터의 기본 개념을 배우고 계속되는 강의에서 자세히 다루겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 포인터는 c언어에서 제공하는 타입중 하나입니다.&amp;nbsp;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;다른 타입과 다르게 포인터 변수는 그값을 주소(어드레스)를 가진다는점이 다릅니다.&lt;/p&gt;
&lt;pre id=&quot;code_1668572406377&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 포인터 변수 선언
char *ptr;

// 포인터 변수에 값을 할당
char sbuf[6];
char *ptr;
ptr = sbuf;

int nVal;
int *nPtr;
nPtr = &amp;amp;nVal;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 포인터 변수는 변수명 앞에 * 를 붙여서 선언합니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 포인터 타입은 앞에서 살펴본 타입으로 선언 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; char *ptr, int *ptr, long *ptr, double *ptr&amp;nbsp; ...&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 포인터 변수의 타입은 대상이 되는 변수의 타입과 일치해야겠지요.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; char에 대한 포인터는 char *, int는 int * ...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 변수가 선언이 되면 메모리가 할당된다고 말씀을 드렸는데 이렇게 메모리가 할당이 되면 메모리의 주소를 갖게 됩니다. 바로 이런 주소를 다루는 변수가 포인터입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ char sbuf[6];&amp;nbsp; 이렇게 선언이 되면 메모리에 6바이트(char가 1바이트, 배열크기가 6)가 할당됩니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; char *ptr; 포인터 변수가 선언되면 이 변수도 메모리에 8바이트(포인터크기)가 할당됩니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; sbuf가 메모리에 할당된 주소를 포인터 변수에 대입해서 사용합니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ptr = sbuf;&amp;nbsp; &amp;nbsp;sbuf에 할당된 메모리 주소를 ptr변수에 대입합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;※ 포인터 변수는 단독(버퍼 없이)으로 사용할 수 없습니다.&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 포인터 변수는 반드시 어떤 메모리의 주소를 할당(값)해서 사용됩니다. &amp;nbsp;(ptr = sbuf 처럼)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 이처럼 어떤 메모리(sbuf[6])가 바로 &lt;b&gt;버퍼&lt;/b&gt;라는 용어로 사용됩니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;즉, 포인터 변수는 버퍼와 같이 사용됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-1) 변수와 포인터 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi pointer.c&lt;/p&gt;
&lt;pre id=&quot;code_1668574203836&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    int nval = 10;
    int *nptr;

    // 단일 변수에 대한 포인터
    printf(&quot;대입전 메모리주소:[%p][%p]\n&quot;, &amp;amp;nval, nptr);
    nptr = &amp;amp;nval;
    printf(&quot;대입후 메모리주소:[%p][%p]\n&quot;, &amp;amp;nval, nptr);
    printf(&quot;값: nval=[%d] nptr=[%d]\n&quot;, nval, *nptr);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668574245047&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o pointer pointer.c
~/c-lecture (master ✘)✭ ᐅ
~/c-lecture (master ✘)✭ ᐅ ./pointer
대입전 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6c40]
대입후 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6b3c]
값: nval=[10] nptr=[10]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열이 아닌 변수가 선언될때 크기 만큼 메모리가 할당되는데 이 메모리를 참조할때는&amp;nbsp;&lt;br /&gt;변수앞에 &amp;amp; 를 붙입니다. 변수앞에 &amp;amp;를 붙이면 이 의미는 변수의 메모리 주소라는 의미입니다.&lt;br /&gt;&lt;i&gt;&lt;b&gt;c언어의 문법입니다. 변수앞에 &amp;amp;를 붙이면 메모리주소다 라고 외워주세요!!&lt;/b&gt;&lt;/i&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;포인터는 주소값을 갖는 변수라고 말씀드렸는데요. 이렇게 변수의 주소를 포인터에 할당할 수 있습니다.&lt;br /&gt;nptr = &amp;amp;nval;&amp;nbsp; &amp;nbsp;--&amp;gt; nval 변수의 주소를 포인터 nptr에 대입&lt;/li&gt;
&lt;li&gt;&lt;i&gt;&lt;b&gt;포인터는 주소값을 갖는 변수지요. 그럼 그 주소에 들어있는 값을 참조할때는 포인터 변수명 앞에&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;* 를 붙입니다.&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;nval 의 값은 10입니다. *nptr의 값도 10이 됩니다.&lt;br /&gt;&amp;amp;nval의 주소는 nptr과 같습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style14&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;변수&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;주소(어드레스)&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;nval&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&amp;amp;nval&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;*nptr&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;nptr&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;*nptr&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예제 실행에서 nptr = &amp;amp;nval; 문 전 printf문입니다.&lt;br /&gt;printf()에서 &lt;b&gt;%p 서식은 주소를 출력하는 서식&lt;/b&gt;입니다. 포인터 공부 하실때 사용하시면 유용합니다.&lt;br /&gt;대입전&amp;nbsp;메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6c40]&lt;br /&gt;2개의 주소가 다르다는걸 아실수 있습니다. nptr값은 선언되면서 무작위의 값이 할당됩니다.(가비지)&lt;br /&gt;nptr = &amp;amp;nval; 할당후 출력되는걸 보시면&lt;br /&gt;대입후 메모리주소:[0x7ffeb6cc6b3c][0x7ffeb6cc6b3c]&lt;br /&gt;같아진걸 보실수 있습니다.&lt;/li&gt;
&lt;li&gt;값을 출력하는 printf문을 보시면&lt;br /&gt;printf(&quot;값:&amp;nbsp;nval=[%d]&amp;nbsp;nptr=[%d]\n&quot;,&amp;nbsp;nval,&amp;nbsp;*nptr);&lt;br /&gt;nval은 변수 자체이지만 포인터 변수 nptr의 값을 출력할때는 *nptr로 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) char 배열과 포인터 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi pointer2.c&lt;/p&gt;
&lt;pre id=&quot;code_1668576228257&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    char sbuf[5] = {'h', 'e', 'l', 'l', 'o'};
    char *sptr;
    int i;

    // 배열 변수에 대한 포인터
    printf(&quot;대입전 메모리주소:[%p][%p]\n&quot;, sbuf, sptr);
    sptr = sbuf;
    printf(&quot;대입후 메모리주소:[%p][%p]\n&quot;, sbuf, sptr);

    // 포인터를 사용해서 sbuf값을 출력
    for (i = 0; i &amp;lt; 5; i++) {
        printf(&quot;sbuf[%d]:주소-[%p][%p] 값-[%c][%c]\n&quot;, i, &amp;amp;sbuf[i], sptr+i, sbuf[i], *(sptr+i));
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668576265017&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o pointer2 pointer2.c
~/c-lecture (master ✘)✭ ᐅ ./pointer2
대입전 메모리주소:[0x7ffda177f183][0x562caed4d080]
대입후 메모리주소:[0x7ffda177f183][0x7ffda177f183]
sbuf[0]:주소-[0x7ffda177f183][0x7ffda177f183] 값-[h][h]
sbuf[1]:주소-[0x7ffda177f184][0x7ffda177f184] 값-[e][e]
sbuf[2]:주소-[0x7ffda177f185][0x7ffda177f185] 값-[l][l]
sbuf[3]:주소-[0x7ffda177f186][0x7ffda177f186] 값-[l][l]
sbuf[4]:주소-[0x7ffda177f187][0x7ffda177f187] 값-[o][o]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;char sbuf[5]; 배열로 선언하면 5바이트 크기의 메모리가 할당됩니다.&amp;nbsp;&lt;br /&gt;일반 변수에서 할당된 메모리를 참조할때는 &amp;amp; 를 붙여서 참조를 했는데&lt;br /&gt;&lt;b&gt;배열에서는 배열 이름 자체가 메모리의 주소가 됩니다. 이부분도 외워주세요!&lt;/b&gt;&lt;br /&gt;char sbuf[5]에 할당된 메모리 주소의 시작은&amp;nbsp; sbuf입니다.&lt;br /&gt;그런데 배열에서 3번째 주소를 알고 싶은 경우는 일반 변수처럼 &amp;amp; 를 붙여줍니다.&lt;br /&gt;sbuf[2] 의 주소는 &amp;amp;sbuf[2] 입니다.&lt;/li&gt;
&lt;li&gt;sptr = sbuf; 포인터 변수 대입전에는 2개의 주소가 서로 다릅니다.&lt;br /&gt;여기서 배열에서는 변수명이 메모리 주소가 되어서 sbuf 를 그대로 포인터 변수에 대입합니다.&lt;br /&gt;sbuf는 배열의 시작 주소라 말씀을 드렸는데요. 그래서 대입문은&lt;br /&gt;sptr = &amp;amp;sbuf[0]; 으로도 가능합니다. 즉, sbuf = &amp;amp;sbuf[0] 입니다.&lt;/li&gt;
&lt;li&gt;포인트 변수 대입전&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;13-1.png&quot; data-origin-width=&quot;2902&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RMPtL/btrRozXyGTL/TUEfGLBVb1Pihn7VX9YqrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RMPtL/btrRozXyGTL/TUEfGLBVb1Pihn7VX9YqrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RMPtL/btrRozXyGTL/TUEfGLBVb1Pihn7VX9YqrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRMPtL%2FbtrRozXyGTL%2FTUEfGLBVb1Pihn7VX9YqrK%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;340&quot; height=&quot;1000&quot; data-filename=&quot;13-1.png&quot; data-origin-width=&quot;2902&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포인트 변수 대입&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;13-2.png&quot; data-origin-width=&quot;3589&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7BS6d/btrRnjIf778/uOrYiAl8cs20nmCD0OnPhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7BS6d/btrRnjIf778/uOrYiAl8cs20nmCD0OnPhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7BS6d/btrRnjIf778/uOrYiAl8cs20nmCD0OnPhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7BS6d%2FbtrRnjIf778%2FuOrYiAl8cs20nmCD0OnPhk%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;340&quot; height=&quot;1000&quot; data-filename=&quot;13-2.png&quot; data-origin-width=&quot;3589&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;printf(&quot;sbuf[%d]:주소-[%p][%p] 값-[%c][%c]\n&quot;, i, &amp;amp;sbuf[i], sptr+i, sbuf[i], *(sptr+i)); 출력문에서&lt;br /&gt;배열 각각의 주소를 출력합니다. &amp;amp;sbuf[i] 로 출력합니다. 또한 포인터 변수로도 출력하는데&amp;nbsp;&lt;br /&gt;그 문법은 sptr+i로 하고 있습니다. 즉, &amp;amp;sbuf[i] == sptr + i 와 같습니다.&lt;br /&gt;값을 출력할때 배열은 sbuf[i] 으로 배열의 값을 출력하고, 포인터로 값을 출력할때는&amp;nbsp;&lt;br /&gt;*(sptr+i) 로 출력합니다. sptr+i 가 각 배열의 주소를 뜻하고 포인터 값에 접근할 경우는 * 를 붙인다고 말씀을 드렸지요. 그래서 *(sptr+i) 주소앞에 * 를 붙인겁니다. 연산자 우선순위가 * 가 + 보다 앞서서 ()로 감싸줍니다.&lt;/li&gt;
&lt;li&gt;주소 출력 부분에서 눈여겨 보실게 있는데요.&lt;br /&gt;sbuf[0]:주소-[0x7ffda177f183]&lt;br /&gt;sbuf[1]:주소-[0x7ffda177f184]&lt;br /&gt;sbuf[2]:주소-[0x7ffda177f185]&lt;br /&gt;sbuf[3]:주소-[0x7ffda177f186]&lt;br /&gt;sbuf[4]:주소-[0x7ffda177f187]&amp;nbsp;&lt;br /&gt;주소를 보시면 +1씩 증가한것을 보실수 있습니다. 이것은 char 타입이 1바이트라서 배열의 다음 주소가 1씩 증가합니다. 이렇게 메모리 주소를 다루는 변수가 포인터입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) int 배열과 포인터 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi pointer3.c&lt;/p&gt;
&lt;pre id=&quot;code_1668577567532&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    int nbuf[5] = {1, 2, 3, 4, 5};
    int *nptr;
    int i;

    // 배열 변수에 대한 포인터
    printf(&quot;대입전 메모리주소:[%p][%p]\n&quot;, nbuf, nptr);
    nptr = nbuf;
    printf(&quot;대입후 메모리주소:[%p][%p]\n&quot;, nbuf, nptr);

    // 포인터를 사용해서 sbuf값을 출력
    for (i = 0; i &amp;lt; 5; i++) {
        printf(&quot;nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n&quot;, i, &amp;amp;nbuf[i], nptr+i, nbuf[i], *(nptr+i));
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668577591286&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o pointer3 pointer3.c
~/c-lecture (master ✘)✭ ᐅ ./pointer3
대입전 메모리주소:[0x7fffeafb5cb0][0x55e4fac89280]
대입후 메모리주소:[0x7fffeafb5cb0][0x7fffeafb5cb0]
nbuf[0]:주소-[0x7fffeafb5cb0][0x7fffeafb5cb0] 값-[1][1]
nbuf[1]:주소-[0x7fffeafb5cb4][0x7fffeafb5cb4] 값-[2][2]
nbuf[2]:주소-[0x7fffeafb5cb8][0x7fffeafb5cb8] 값-[3][3]
nbuf[3]:주소-[0x7fffeafb5cbc][0x7fffeafb5cbc] 값-[4][4]
nbuf[4]:주소-[0x7fffeafb5cc0][0x7fffeafb5cc0] 값-[5][5]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;char 배열을 int 배열로 바꿘본 예제입니다.&lt;br /&gt;실행한 주소를 보시면 char 는 주소가 1씩 증가를 했는데 int 배열은 4씩 증가한 걸 보실수 있습니다.&lt;br /&gt;int 타입의 크기가 4바이트입니다. 이렇게 타입에 따라서 메모리가 할당된 모습을 확인하실 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668577877277&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf(&quot;nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n&quot;, i, &amp;amp;nbuf[i], nptr+i, nbuf[i], *(nptr+i));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 이문장을&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1668577922891&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf(&quot;nbuf[%d]:주소-[%p][%p] 값-[%d][%d]\n&quot;, i, &amp;amp;nbuf[i], nptr, nbuf[i], *nptr);
nptr++;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이렇게 변경 가능합니다.&lt;br /&gt;&amp;nbsp; nptr주소로 *nptr은 주소에 대한 값으로 사용합니다.&lt;br /&gt;&amp;nbsp; nptr++; ++연산자로 포인터를 다음 데이타로 이동시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; nptr = &amp;amp;nbuf[0];&amp;nbsp; &amp;nbsp; -&amp;gt; 1번째 배열 주소&lt;br /&gt;&amp;nbsp; nptr++;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;--&amp;gt; 2번째 배열 주소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; nptr++;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;--&amp;gt; 3번째 배열 주소&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; 포인터의 ++, -- 연산자는 struct 문법에서 다시 자세히 다루겠습니다.&lt;/p&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>Pointer</category>
      <category>리눅스</category>
      <category>포인터</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/19</guid>
      <comments>https://dayudev.tistory.com/19#entry19comment</comments>
      <pubDate>Wed, 16 Nov 2022 14:07:33 +0900</pubDate>
    </item>
    <item>
      <title>12. 문자열(string)</title>
      <link>https://dayudev.tistory.com/17</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 목표&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 이해하기&lt;/li&gt;
&lt;li&gt;문자열 활용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 설명&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ c언어에서 문자열이라는 것은 char, int와 같이 타입이 존재하는건 아닙니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 문자열(string)은 null(널)로 끝나는 문자의 집합입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1668559898345&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 문자 타입의 배열
char cbuf[5] = {'h', 'e', 'l', 'l', 'o'};

// 문자 타입의 배열 이면서 마지막값이 null이므로 문자열이 됩니다.
// null 표현 : '\0', 0x00, 0
char sbuf[6] = {'h', 'e', 'l', 'l', 'o', '\0'};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ 차이점을 아시겠습니까?&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cbuf[5] 배열은 마지막 문자가 null이 아니므로 문자열이 아닙니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sbuf[6] 배열은 마지막 문자가 null이므로 문자열입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;u&gt;&lt;b&gt;※ 마지막 null문자도 1바이트를 차지합니다. &lt;/b&gt;&lt;/u&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;u&gt;그래서 문자열로 만드실 경우 문자수 + 1로 배열/메모리를 확보하셔야 합니다.&lt;/u&gt;&lt;/b&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;3-1) 예제프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi string.c&lt;/p&gt;
&lt;pre id=&quot;code_1668563342888&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    char sbuf[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
    int i;

    // 배열의 값을 출력해 봅니다.
    printf(&quot;----- sbuf 출력 -----\n&quot;);
    for (i = 0; i &amp;lt; 6; i++) {
        printf(&quot;sbuf[%d]=%c\n&quot;, i, sbuf[i]);
    }

    // 문자열을 출력합니다.
    printf(&quot;----- 문자열 출력 -----\n&quot;);
    printf(&quot;sbuf[%s]\n&quot;, sbuf);

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668563447116&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o string string.c
~/c-lecture (master ✘)✭ ᐅ ./string
----- sbuf 출력 -----
sbuf[0]=h
sbuf[1]=e
sbuf[2]=l
sbuf[3]=l
sbuf[4]=o
sbuf[5]=
----- 문자열 출력 -----
sbuf[hello]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;pre id=&quot;code_1668563492774&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;char sbuf[6] = {'h', 'e', 'l', 'l', 'o', '\0'};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;char타입 배열을 선언과 동시에 값을 할당하는데 마지막에 null문자('\0')를 넣어서 문자열로 만듭니다.&lt;/li&gt;
&lt;li&gt;for 문으로 배열의 값을 출력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1668563601333&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf(&quot;sbuf[%s]\n&quot;, sbuf);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;printf문의 서식 %s 로 문자열을 출력합니다.&amp;nbsp;&lt;br /&gt;%s 서식을 사용하실때 해당하는 값은 변수명만을 사용했습니다.&lt;br /&gt;(포인터에서 자세히 다루도록 하겠습니다.)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-2) 아스키코드값 출력하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi string2.c&lt;/p&gt;
&lt;pre id=&quot;code_1668563942316&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    char sbuf[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
    int i;

    // 배열의 값을 출력해 봅니다.
    printf(&quot;----- sbuf 아스키코드 출력 -----\n&quot;);
    for (i = 0; i &amp;lt; 6; i++) {
        printf(&quot;sbuf[%d]=%c:[%d]:[%x]\n&quot;, i, sbuf[i], sbuf[i], sbuf[i]);
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668563970979&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o string2 string2.c
~/c-lecture (master ✘)✭ ᐅ ./string2
----- sbuf 아스키코드 출력 -----
sbuf[0]=h:[104]:[68]
sbuf[1]=e:[101]:[65]
sbuf[2]=l:[108]:[6c]
sbuf[3]=l:[108]:[6c]
sbuf[4]=o:[111]:[6f]
sbuf[5]=:[0]:[0]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;pre id=&quot;code_1668563999483&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;printf(&quot;sbuf[%d]=%c:[%d]:[%x]\n&quot;, i, sbuf[i], sbuf[i], sbuf[i]);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;%c다음의 [%d]:[%x]가 있습니다.&lt;br /&gt;printf문 서식에서 %d는 알고 계신데로 정수형이고 %x는 16진수로 표현하는 서식입니다.&lt;br /&gt;같은값 sbuf[i] 를 %c, %d, %x로 출력할 수 있습니다.&lt;/li&gt;
&lt;li&gt;출력중 알파벳 h 값은 아스키코드값은 104이고 16진수로는 0x68인 것을 나타냅니다.&lt;br /&gt;(c언어에서 16진수를 표시할때 0x를 붙입니다.)&lt;/li&gt;
&lt;li&gt;man ascii 로 매뉴얼을 보시면 더 자세히 알수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3-3) string 선언 예제 프로그램&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; ▶ vi string3.c&lt;/p&gt;
&lt;pre id=&quot;code_1668640879918&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main() {
    // 문자열로 선언
    char sbuf[] = &quot;hello&quot;;
    int i;

    // 배열의 값을 출력해 봅니다.
    printf(&quot;----- sbuf 아스키코드 출력 -----\n&quot;);
    for (i = 0; i &amp;lt; 6; i++) {
        printf(&quot;sbuf[%d]=%c:[%d]:[%x]\n&quot;, i, sbuf[i], sbuf[i], sbuf[i]);
    }

    return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 컴파일/실행&lt;/p&gt;
&lt;pre id=&quot;code_1668640906738&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;~/c-lecture (master ✘)✭ ᐅ gcc -o string3 string3.c
~/c-lecture (master ✘)✭ ᐅ ./string3
----- sbuf 아스키코드 출력 -----
sbuf[0]=h:[104]:[68]
sbuf[1]=e:[101]:[65]
sbuf[2]=l:[108]:[6c]
sbuf[3]=l:[108]:[6c]
sbuf[4]=o:[111]:[6f]
sbuf[5]=:[0]:[0]
~/c-lecture (master ✘)✭ ᐅ&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;▶ 분석&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 예제와 동일한 결과를 나타냅니다.&lt;/li&gt;
&lt;li&gt;배열에 문자열을 바로 할당하는 문법입니다.&lt;br /&gt;char&amp;nbsp;sbuf[]&amp;nbsp;=&amp;nbsp;&quot;hello&quot;;&lt;br /&gt;이 선언은 char sbuf[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; 와 같은 효과를 냅니다.&lt;br /&gt;문자열을 바로 선언해서 사용하고자 할 경우 편리합니다.&lt;br /&gt;※ 문자열을 좀 더 자세히 다룰때 다른 형태를 살펴보겠습니다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 여기서는 문자열을 선언할떄 이런형태로 선언하는구나. 정도만 아셔도 됩니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>리눅스 C-언어 초급과정</category>
      <category>C언어</category>
      <category>GCC</category>
      <category>String</category>
      <category>리눅스</category>
      <category>스트링</category>
      <author>다유데브</author>
      <guid isPermaLink="true">https://dayudev.tistory.com/17</guid>
      <comments>https://dayudev.tistory.com/17#entry17comment</comments>
      <pubDate>Wed, 16 Nov 2022 11:07:12 +0900</pubDate>
    </item>
  </channel>
</rss>