기술을 이해하는 기획자를 꿈꾸는 경영학도의 데이터 디자이너 도전기

People propose, science studies, tech follows -Don Norman-

문송하다는 말이 어느새 정설이 되었고, 모두가 기술을 배워야 한다고 입을 모아 말하는 와중에 나는 그 사이에 서서 고민하던 경영학 전공자였다. 4차 산업혁명이니 Digital Transformation이니 기술에 대한 논의가 오르내리는 세상에서 고작 4년동안 학교수업을 듣고 고작 가끔씩 HBR/DBR 아티클이나 훑어보는 나는 어디까지나 티끌같은 주변인이었다.

주변인이고 싶지 않았다. 기술적인 이야기가 피부에 와닿지 않은채 그저 피상적으로 들리고 진정성과 효용성에 의심이 가는 까닭이 바로 내가 직접 해보지 않아서, 잘 알지 못해서라는 것을 깨달았다. 서툴지만 직접 기술을 만져보기로 결심했다.

기술을 이해하는 기획자.
다른 필드의 사람들이 협업하는 과정에서 발생하는 충돌의 유화제의 역할을 하는 코디네이터
>>> 궁극적으로 내가 지향하는 것.

People propose, science studies, tech follows.

기술은 중요하지만, 결국 그도 사람을 따라야한다는 가장 중요한 원칙을 안고 시작한 “기술과 사람을 연결하는 기획자가 되기위한 기술 이해의 여정”, 그 첫 스타트는 데이터 시각화 교육과정이었던 꿈꾸는 데이터 디자이너(이하 꿈데디)였다.

프로그램이 끝난지 벌써 반년이 넘는 시간이 흐른 와중에 내가 뒤늦은 후기를 적기로 한 이유는
그때의 나와 지금의 나가 어떻게 성장했는지 살펴보기 위함이오,
과거의 열정을 다시 되새김질 하며 지금 나를 다시 가다듬기 위함이오,
이런 피드백을 통해 앞으로의 방향성을 잡아보기 위함이다.

과거와 현재, 미래가 공존하는 과정의 이 후기는 아직 열린 결말이다.

 

꿈데디 전과 후 달라진 것들

 

꿈데디를 시작하기 전:

데이터 시각화와 인포그래픽스에 어떤 차이가 있는지 조차 몰랐다.

데이터보다 직관을 더 믿었다.

코딩경험이라고는 간단한 HTML태그 조금과 관심으로 발톱정도 들여놓다만 eDX Harvard University의 CS50 강의 수강.

Raw 데이터를 확인하여 직접검토하기보다 어느 기관에서 나온 보고서에 인용된 자료를 짜깁기하고 PPT형태로 포장하는 것을 주로 했다.

내가 경험한 팀프로젝트는 경영학과에서 주로하던 경영사례발굴, 보고서에서만 현실화 시켜본 마케팅 프로젝트(공모전 포함), 그 외 대외활동 등등이라 하겠다. 이들의 공통점은 대학생이 주축이라는 점과 프레젠테이션이 최대 아웃풋이라는 점에 있다.

꿈데디가 시작된지 1년이 지났다

데이터 시각화의 전문가가 되진 않았으나, 최소한 그것이 왜 중요하고, 어떻게 쓰이며, 전문가가 되고자 한다면 도움을 구할 책과 사람을 알게 되었다.

직관은 인간의 선택에 있어 가장 중요한 요소지만, 데이터가 함께하는 직관과 없는 직관은 타인을 설득함에 있어 커다란 차이가 난다. 내가 특정 분야에 오랜 전문가가 아니라면 더더욱.

꿈데디에서 R과 D3.js를 배웠고 프로젝트를하며 야매로 자바스크립트를 속성으로 건드려보았다. 문과>>> 코딩 >>>> ??? >>>>   상태는 벗어났다. 코딩은 언어학습과 비슷한 측면이 있는데, 영어를 잘하려면 두려움을 버리고 자주 사용해야 하듯 코딩또한 마찬가지다. 막연한 두려움이 없어졌기에 필요하다면 구글링으로 학습하고 뭔가를 만들 수 있게 됐다. 다른 언어를 시도해볼 엄두를 낼 수 있는 건 덤이라 C와 C++까지 입문했다. 그다음은 파이썬을 해볼 생각이다.

구글링을 통해 얻은 보고서에 있는 인용 데이터나 차트를 직접 검토할 수 있게 됐다. 맘에 안들면 새로 차트를 만들 수 있고, Raw 데이터를 찾다보면 새로운 인사이트를 발굴 해낼 수도있다. 공공데이터를 활용할 수 있게된 것은 덤이고 그것이 활용하기 어려운 형태인것은 함정이다.

감히 말하길 내 인생에서 제대로 해본 첫 팀프로젝트라 하겠다. 감히 가장 어린 나이에 짧은 가방끈과 경험치로 그렇게 우수한 사람들과 함께 팀프로젝트를 진행하고 이름도 거창한 프로젝트 매니저를 달아본 것은 앞으로도 감사할 것이다.

엑셀로 3D맵을 만들 수 있다고?

Microsoft Office Marketing Team에서 일할 때의 일이다. 나는 Office 365의 디지털 마케팅을 위한 컨텐츠를 제작하고 Social Channel을 관리하는 역할을 맡았다. Microsoft Excel 2016의 마케팅 영상에서 내 눈을 사로 잡는 것이 있었으니, 바로 3D Mapping기능이었다. 한국어로 실제로 실행에 옮길 만한 튜토리얼이 없다는 것에 안타까움을 금치 않을 수 없었던 나는 ‘어떻게 엑셀로 3D 매핑을 할 수 있을까’를 익힌 후 ‘Excel로 3D맵 만드는 가장 친절한 설명서‘ 를 제작했다.
다소 매니악한 정보였음에도 불구하고 내가 만든 오피스 컨텐츠 중 가장 많은 반응을 이끌어 낸 것이 바로 ‘데이터 시각화 – 매핑’이었다는 사실에 만든 나도 놀랐다. 심지어 내가 더이상 Office 페북지기가 아니게 된 다음에도 두어명의 사용자분이 내게 엑셀 매핑 컨텐츠에 대한 상세 내용을 개인적으로 문의하기도 했다. 데이터 시각화에 대한 사람들의 관심을 체감했던 일이다.

12930999_1015987948469407_8897234795294571871_n

엑셀로 3D맵을 만드는 가장 친절한 설명서 : 꿈데디가 있었기에 만든 컨텐츠라 하겠다

 

 

 

다양한 관점을 조율했던 내인생 첫 리얼 협업 팀프로젝트

꿈데디 전반에 걸쳐 데이터 시각화 관련된 팀 프로젝트를 수행했다. 우리 팀은 총 6명이었는데, 나는 그 중에서 가장 어렸고, 가방끈도 짧았으며, 당연히 경험치도 낮았다. 그럼에도 불구하고 나는 첫 오리엔테이션때의 팀회의 결과 무려 PM이 되었다. 첫 만남인지라 대면대면했던 사람들 사이에서 용감(?)하고 적극적으로 보이는 성격 덕분에 얻게된 자리였다. 오리엔테이션날 스케치북에 팀 소개를 마커로 그려서 모두의 앞에서 소개하는 시간이 있었는데, 원래 브레인스토밍을 가장한 낙서필기를 많이하고 산 내가 주저없이 펜을 잡고 그림을 그려나가는 대담한 모습이 아마 가산점을 받았던게 아닌가 생각한다.

나이 자체로는 주눅 들지 않는 선천적 명랑쾌활함을 지닌 나지만,  고만고만한 대학생들끼리 행하는 학교 과제나 대외활동, 공모전과 같은 팀을 꾸려본게 내 팀플 인생의 전부인지라, 나보다 경험치가 높은 다양한 분야의 사람들에게 내가 무엇을 해줄 수 있을까 걱정이 되기도 부담이 되기도 했었다. 회의 때마다 다양한 의견이 나오지만, 가장 중요한 첫단추인 주제 선정에는 오랜시간 어려움을 겪었던 문제가 제일 컸다. 주제 선정에 오랜 시간이 걸렸던 중심에 PM이었던 내가 있었다.

경영학과를 전공하여 기획자 성향이 강한 나는 실행적 관점의 디테일한 그림보다는 큰 그림을 그리는데 익숙했다. 회의에서 주제가 나올 때마다 ‘그래서 이 프로젝트가 어떤 가치를 줄 수 있을까’ ‘이 서비스를 만들면 사용자의 어떤 니즈를 충족시켜줄 수 있을까’ ‘우리가 이 시각화를 어떻게 구현할 수 있을까, 가능은 한가?’ 에 너무 초점을 맞추다 보니 주제는 자꾸 엎어져 원점으로 돌아가기 일수였다. 목적성과 방향성을 계속 견지해 나가야 한다는 나의 관점과, 프로젝트를 진행해 나가기 위해서는 일단 자원과 시간을 투입해 봐야한다는 관점의 차이를 조율하는 시간이 흘러가는 와중에, 가장 적합한 나의 역할은 버릴 것은 버리고 중요한 것만 취하여 빠르게 결정하고, 롤을 배정하여 신속하게 프로젝트를 추진하면서 지속적인 피드백을 반복하고 수정하는 것이었다.

13344570_1032812526805633_34835980628027796_n

꿈데디 당시 가장 경험치가 높아 내가 많이 의지하고 조언을 구하던 언니가 데이터 컨설턴트가 되어 쓴 후기(데이터 사이언티스트로 성장하기)에서 발췌한 꿈데디 프로젝트의 단상. 저기에 방향성을 강조하던 기획자, Skill-set을 엑셀로 관리하던 취준생이 >>> 나다. 감사하게도 나와의 논쟁이 다양한 관점을 견지하는데 조금이라도 도움이 되셨다니 다행일 따름이다.

수십가지의 아이디어들이 스쳐간 자리의 끝에는 빠른 주제선정이 남아있었다. 처음 선정했던 주제는 ‘서울의 밤’. 그러나 서울의 밤을 몇시부터 몇시까지 규정할 것인가부터 밤에 관한 데이터 수집의 어려움에 봉착했다. 쓸모있을만한 데이터, 예를 들어 전력량 시간별 세부 데이터와 같은 것은 대개 접근할 수 없는 것들이 많았다. 몇 차례의 삽질을 거듭한 결과 우리는 주제를 바꾸었다.

최종 발표일을 불과 3주정도 남겨놓고 Team Tada의 Project I. HANGANG. U는 시작되었다.

촉박한 시간 아래서 우리는 커뮤니케이션과 조율상에 발생하는 잡음을 최소화하고 빠르고 정확한 실행에 모든 자원을 집중해야만 했다. 우선 팀 커뮤니케이션을 위해 사용해보았던 다양한 도구(Slack, Google docs, etc)들을 카톡으로 일원화 시켰다. 팀 회의때마다 작성되는 회의록은 파워포인트 슬라이드 한장에 담아 누가 무엇을 다음 회의까지 해올 것인지 이미지로 카톡방에 공유했다.

제목 없음.png

프로젝트 실행은 이렇게 이루어졌다. Brainstorming ~ 주제선정까지가 제일 길었던 것은 함정

 

제목 없음.png

촉박한 시간, 빠른 실행을 위해 가장 단순화 시킨 회의록. 회의가 끝나자마자 카톡방에 이러한 이미지들을 뿌려 접근성과 명시성을 높였다.

 

우리 프로젝트는 한강의 정보를 보다 한눈에 시각화 하는 데 목적을 두었다. 아무래도 상대적으로 수집하기 쉬운 데이터를 선택하여 수집에 들어가는 시간을 줄이고 대신 있는 데이터를 잘 활용한다는 측면에 한정된 시간을 집중하기 위해서였다. 나는 한강에서 즐길 수 있을 만한 장소를 한데 모아 하나의 지도에 맵핑하고, 네비게이션 기능을 추가한 Customized Map을 만드는 일을 맡았다. 한강과 관련된 공공데이터를 모아 정제하고, 그 데이터를 Mapbox에 Geotagging한 이후에 이미지는 수작업으로 HTML태그를 삽입했다. 네비게이션 기능이나 체크박스 기능은 mapbox.js와 API를 활용하였다. 덕분에 약간의 javascript를 속성으로 독학하는 효과를 거두었다.

캡처.PNG

Mapbox로 구현한 Customized HanGang Map.

 

놀랍고도 고마운 것은 훌륭한 팀원들과 적절한 팀워크(+모티베이션)를 이룬다는 전제 하에 팀프로젝트가 놀랍게도 자생하며 굴러갔다는 점이다. 내가 대학생때 겪은 상당수의 팀프로젝트에서는 누군가가 총대를 메야만 겨우 굴러가는 형태가 많았기에 이는 참으로 독특한 경험이었다. 프로그램 후반부로 갈수록 누구나 그렇듯 초반의 에너지가 고갈되어가고 소진되어가는 와중에, 차례대로 지치더라도 마치 병렬식 콘센트마냥 나머지 사람들이 빈 에너지를 맞춰주는 놀라운 광경을 경험한 것이다. 타고 난 것이 에너지와 열정이 넘쳐 주로 하드캐리와 모티베이션과 같은 것들을 담당하던 나조차 취업준비와 학교수업에 꿈데디, PM이라는 감투까지 겹친 상황이 버거웠는데, 다들 지쳐도 누구하나 책무를 놔버리는 사람은 없이 팀을 지켜줌에 너무나도 감사했다.

제목 없음.png

각자 출중한 능력을 갖고 계신 만큼 각지에서 활약하고 계신 Tada 멤버들

 

최종발표 전날 광화문 서울 창조경제혁신센터에서 밤을 새고 난 다음날의 최종발표 당일까지 발표자료만들고 사이트 만지던 그 날. 누군가는 내가 역량을 다 발휘하지 못한 것으로 보여 아쉽다는 말을 전하기도 했지만, 그동안 발표자료 만들고 발표하는 것에 특화됐던 흔한 경영학과 학생이 기술을 직접 만지느라 밤을 지새워본 경험 그자체만으로 나는 만족했다.

결과적으로 눈이 딱 벌어질만한 결과물이 나왔더라면 더더욱 좋았겠지만, 이 프로젝트는 내게 과정자체만으로 포트폴리오를 상회하는 경험을 선사해준 고마운 존재였다. 이번 경험을 토대로 다음에는 목적의식을 뚜렷이 하면서도, 신속하게 의사결정하고, 기술과 사람을 이해하여 잡음을 최소화하고, 행동을 명확하게 Drive해서 Lean한 프로젝트를 구성할 수 있는 그런 기획자가 되도록 정진할 것이다.

 
 
파워포인트로 만들어본 I.HanGang.U 프로젝트 소개영상. 게임 튜토리얼 형태로 제작해 봤다. 프로젝트 사이트: http://datada.net

 

나는 잘 알지도 못하면서 입으로만 포장하는 주변인이 되는 것을 경계할 것이다.

기술과 사람을 연결하는 진정성 기획자가 되기 위한 여정의 시작을 멋지게 써준
꿈데디에 특별한 감사를 뒤늦게 다시 전한다.

 

 

APPENDIX: 당시 프로그램 지원시 작성했던 지원동기 

계속 읽기

TIPS C++ 강의노트 2. This포인터, 상속, 오버로딩/라이딩, Scope, Namespace, 다형성

접근제한자

  • 외부 클래스에서 해당 클래스의 멤버 변수와 멤버 함수의 사용 여부를 결정하기 위해 사용하는 것
  • 함수를 만들도록 강제함
  • 멤버의 앞에 private, public, protected 키워드와 : 를 함께 사용하여 명시
  • 클래스에서 어떤 접근 제한자도 명시하지 않을 경우 기본적으로 멤버가 private권한
  • Private:
    외부 클래스에서 해당 클래스 멤버의 접근이 불가능하며, 클래스 내에서만 사용 가능. C++에서는 정보 은닉을 위하여 기본적으로 멤버 변수가 private 권한을 갖도록 선언함

    class Student 
    { 
    private:
        int age:
    };
     void main()
     {
        Student data;
        data. age=5; // 컴파일시 Error! }
    
    *** private을 public으로 하면 에러안남 
    *** 기계어로 바뀔 때 미치는 영향은 없음

 

  • Public:
    외부 클래스에서 해당 클래스 멤버의 접근 가능. 주로 멤버 변수들을 외부 클래스에서 사용할 수 있도록 하는 인터페이스들을 public으로 선언

    class Student
     {
     private:
        int age;
     public:
        Student()
        {
          age = 0;
        }
        void SetAge(int a)
        {
          age = a;
        }
     };
     void main()
     {
        Student data;
        data.age=5; // Error
        data.SetAge(5); }

 

This 포인터

  • C로만들면 
    struct MyData 
     {
        int data;
     };
     void SetMyData(MyData *parm_temp, int parm_data)
     {
        parm_temp->data=parm_data;
     }
     void main()
     {
        MyData temp;
        temp.data=5; // 직접 접근
        SetMyData(&temp, 5); // 간접 접근 
    }
    C++ 
    class MyData
     {
     private:
        int data;
     public:
        void SetMyData( MyData *parm_temp int parm_data) // 회색은 생략
        {
          data=parm_data;
        }
     };

 

  • 현재 활정화된 객체의 주소를 가지고 있는 포인터
    클래스명*const this;
  • 클래스 내부에서 현재 작업중인 객체의 멤버 변수나 멤버 함수에 접근하기 위해 컴파일러가 내부에서 선언
    class MyData
     {
     private:
        int data;
     public:
        void SetMyData(int parm_data)
        {
          MyData *const this; //숨겨진 코드
               data_parm_data;
        }
     }
    
     *** this->data=parm_data; // 컴파일러 해석 >>> 숨겨진 코드 다음줄에 넣기
  • :: scope연산자
    >>> 누구에게 소속되지 않음. 전역변수로. C++에서는 더 다양한 영역 표현을 할 수 있음
  • 네이밍 중복을 피하는 변수 표현
    전역변수는 일반적으로 g_data
    지역변수는 a_data
    멤버변수는 m_data

 

This 포인터의 상수화

  • Const 키워드를 함수 반환 값 앞에 명시하는 경우 반환 값이 상수화
  • Const 키워드를 함수 선언 후 뒤에 명시하면 this 포인터가 가리키는 값이 상수화
    Class MyData
     {
     private:
        int data;
     public:
        void SetMyData(int parm_data) const
        {
          const MyData *const this;
          this->data=parm_data; >>> 컴파일시 Error!
        }
     }; *** const 사용으로 사용자의 실수 Error 방지
  • Reference [ 칠판 ]

 

 

상속(inheritance)

  • 웹 페이지에서와 같이 프로그램을 작성할 때에도 많은 코드의 중복 발생
  • 코드의 중복은 비슷한 기능을 하는 클래스의 코드를 그대로 복사해서 사용하기 때문에 많이 발생. 따라서 웹페이지의 링크와 같은 개념을 도입하여 중복된 코드를 쓰지 않도록 하는 것이 상속
  • 상속 문법을 사용하면 “동일한 코드가 명시한 곳에 있으니 이 클래스는 해당 클래스와 기본적으로 동일하다.”는 뜻으로 컴파일러가 판단
    class work // >>> work를 만드는 것이 아니라 clone work {} 로 소스상의 코드 중복을 피함
     {
        int data; public:
        void SetData(int a){
        data=a;
        }
     };
    class A // 부모 클래스
     {
        int Add(int a, int b)
        {
          return a+b;
        }
     }; class B : public A // 자식 클래스. Public A는 상속방식. A에 있는 내용을 그대로 B에 복제하겠다
     {
     };
     void main()
     {
        A a;
        int num1=a.Add(3, 5);
    
        B b;
        num1=b.Add(1, 4);
     }

 

상속 등급

  • 부모 클래스를 어떤 등급으로 상속하느냐에 따라 자식 클래스에서 부모 클래스 멤버에 접근할 수 있는 등급이 달라진다
  • Protected는 사용에 따라 접근방식(접근 등급 상승)이 달라진다
  • 대부분의 경우 public 상속 등급을 사용한다
    class Parent
     {
     private: // private는 상속이 되지 않음
        int debt;
     protected: // protected는 상속됨
        int property; public:
        int GetDebt()
        int GetProperty() }; 
    
    *** 상속이 되지 않은 상태면 private와 protected는 동급이나 상속이 되면 달라짐

 

오버로딩

  • C++에서는 함수 명만으로 함수를 구분짓는 C와 달리 인자의 개수나 인자의 데이터 형을 달리하여 동일한 이름의 함수를 사용할 수 있도록 제공. 이것을 함수 오버로딩(Overloading)이라 함
  • 단, 함수의 반환형만 다른 경우 동일한 함수로 인식되기 때문에 주의해야 함
    int Sum(int a, int b)
     {
        return a+b; } 
    
         ▲▼ 별개의 함수
    
     double Sum(double a, double b)
     {   
     return a+b;
     }
    
     *** 함수의 반환값은 오버로딩 제공 안함
    int Sum(int a, int b)
     {
        return a+b;
     }
    
        ▲▼ 동일한 함수
     short int Sum(int a, int b)
     {
        return(short int)(a+b);
     }

 

오버라이딩

  • 클래스 간의 상속 관계에서 상위 클래스에 존재하는 함수를 하위 클래스에서 기능을 재정의하여 사용하는 것
  • 오버라이딩은 오버로딩과 달리 함수의 이름, 인자의 개수, 인자의 데이터 타입이 정확히 일치해야 함
  • 더 많이 씀
  • 상속관계에 적용되는 기능. c.f. 오버로딩은 모든 함수에서 씀
    [오버라이딩 함수 예제] 
    class A
     {
        void PrintName()
        {
               printf("Tipssoft!!")
        }
     };
    
     class B : public A {
        void PrintName()
        {
               printf("Tipsware:)")
        }
     }
    
     void main()
     {
        B b;
        b.PrintName(); // B 클래스의 함수 호출
     } 
    
    *** 빨간 부분을 스코프연산을 쓰면
     void PrintName()
     {
        A :: Print Name():
           printf("Tipsware:)");
     };

 

Allocation & Instance

  • 할당(Allocation) : 메모리 할당. C++에서는 못씀
    struct People data;
    int num=5;
    char arr[10];
  • 인스턴스(Instance) : 메모리를 할당함과 동시에 객체를 초기화

 

객체의 동적 할당

  • 클래스를 사용하기 위해 동적으로 메모리를 할당하고 해제하는 방법에는 두 가지가 존재.
    1. malloc-free
    2. new-delete
  • malloc-free

    동적으로 메모리를 할당하고 해제할 수 있으나, 객체 생성자와 객체 파괴자가 정상적으로 수행되지 않기 때문에 클래스 객체 생성시에는 사용하지 않는다

     struct People *p = (People *)malloc(sizeof(People));
     class Student *p = (Student*)malloc(sizeof(Student)); 
    >>> 에러는 아니지만, 클래스가 정상적으로 생성되지 않음
  • new – delete (preferred)

    클래스 객체를 동적으로 할당하고 초기화 하기 위해 (instance) 사용되는 연산자.
    New 연산자를 사용하여 객체를 생성하면 해당 객체는 Heap에 할당.
    New 연산자로 할당한 메모리는 반드시 delete 연산자로 해제해 주어야 함

    함수는 사용자지정. 연산자는 문법이 제공하는 것.

    Student *p = new Student(); 
    // 객체가 할당되고 Student클래스의 객체 생성자가 호출
    delete p; 
    // new 연산자로 할당된 메모리가 해제되며 객체 파괴자가 호출
    int *p_num = new int[5]; delete[] p_num; 
    // 기본 데이터 형도 new 연산자를 사용하여 할당할 수 있으며 
    배열형메모리를 할당하는 경우에는 해제 시에 delete옆에 []를 명시해야 한다
    int *p = (int*)malloc(sizeof(int)); 
    >>> int *p = new int;
    int data [5];
    int *p = new int[5];
    
    해제: 
    delete[] p; 
    
    *** [] 주의해야함

 

Scope 연산자

  • C에서는 지역 변수와 전역 변수의 이름이 동일할 경우 지역 변수가 선언된 함수에서 전역 변수를 호출할 수 있는 방법이 없었음
  • C++ 에서는 scope 연산자를 이용하여 전역 변수에도 접근할 수 있게 됨. 전역 변수 앞에 :: 를 붙여주면 전역 변수 의미
C C++
int data;

 

void main()

{    int data = 3;

data= 5;    //지역 변수의 값이 변경

}

int data;

void main()

{ int data = 3;

::data= 5; // 전역 변수의 값이 변경

}

 

 

Namespace

  • C++에서 함수의 변수의 이름이 중복되는 것을 막아주고, 코드의 가독성을 높이기 위해 Namespace라는 문법을 제공한다
  • 매번 네임스페이스를 명시하는 번거로움을 줄이기 위해 using이라는 키워드를 사용하여 해당 네임스페이스를 미리 정의할 수 있다
    namespace A 
    {    
    int data;
     }
     namespace B
     {    
    int data;
     }
     using namespace A;
     void main()
     {
       A::data = 5; // namespaceA에 선언된 변수에 5 저장 
       B::data = 3; // namespaceB에 선언된 변수에 3 저장
     };;
  • 매번 네임스페이스 명시하는 번거로움 줄이기 위해 using이라는 키워드를 사용하여 해당 네임스페이스를 미리 정의할 수 있다. using namespace A; *** 둘 중에 하나만 using namespace
  • Namespace 예제
class Student

{ private:    Int my_age;

public:

void SetAge(int age)    {    my_age = age;    }    int GetAge()    {

return my_age;

} };

class Student

{ private:

int my-age;

public:

void setAge(int age);

int GetAge(); }; void Student::SetAge(int age)

{ my_age = age;

} int Student: GetAge() {

return my_age;

}

 

 

 

다형성

 

다형성(Polymorphism): 부모클래스의 포인터로 자식 클래스의 변수를 받아서 객체를 정의할 수 있는 것

Struct A

{    int data 1; };

 

Struct B {    int data 1;    int data 2; };

 

A temp 1; A *p = &temp1;

B temp 2;

B *p = &temp2;

 

class A

{ public: void Test() { } };

 

class B : public A { public: void Test() {   } }; B data; data.Test(); B data: A *p = &B; p->Test(); // A출력

 

다형성 virtual 쓰면 A아닌 B출력

함수 이름은 유지하면서 내용은 바뀌는 것이 오버라이딩

 

동물농장

Class Animal

{

Public:

virtual Void Eat () {} virtual void sound () {}

};

 

Class Dog: public Animal

{

Public:

void eat() { “개밥” }

Void sound() { “멍멍” }

};

 

Class Cat: public Animal {

Public:

Void Eat () { “고양이밥” }

Void sound () { “야옹” }

}

 

Animal *p[5];

p[0] = new Dog;

p[1] = new Cat;

p[2] = new Dog;

*** animal이 dog와 cat을 둘다 받을 수 있음.

 

For(i=0; i<5; i++)

p[i] -> Eat();

 

변화에 더 유연하고 효율적으로 대응할 수 있음

TIPS C++ 강의노트 1. 객체지향, 클래스

C와 C++

C와 C++은 쓰는 문법 비슷하다.

차이는 C는 자율성이 강한데 반해, C++는 객체지향으로 자율성에 제한된다. 비유하자면 C는 설계도가 없는 장난감 C++ 설계도가 있는 장난감이다. 설계도가 없는 장난감은 창작자의 능력 여하에 따라 아주 좋은 장난감이 만들어 질 수도 있고, 아닐 수도 있어 편차가 심한데 반해 설계도가 있는 장난감은 자율성이 떨어져서 높은 수준의 장난감의 나오기는 힘들겠지만 어느정도 준수한 장난감을 만들 수 있다.

즉,  C는 프로그래머가 철학을 가져야 하고 C++은 프로그래밍 자체에 철학이 있다.

C의 특징 (편의점)

Data와 함수가 개별적으로 운용됨 >>> 따로 놀음.
장점: 빠르게 자기가 원하는 데이터를 찾아서 가져갈 수 있음.

단점: 데이터 구조의 변화가 있을 때 함수 코드 변화도 있어야 함. 그러나 잘 쓰면 극복할 수 있음

>>> 코드의 유지 보수가 어렵다. 일반적인 프로그래머라면 변화에 대응하기가 어려움

C++의 특징 (은행)

장점: 밖에 있는 사람들은 안에 있는 내용을 알 필요가 없음. 데이터의 변화가 와도 실제 함수에는 영향이 최소화. 보안이 더 잘 지켜진다.

단점: 느림

 

반드시 좋은 기술은 없다. 상황에 따라 맞는 기술이 있을 뿐

 

객체지향

  • C언어에서는 모듈(Module)이라는 개념을 제공했다. 모듈은 함수의 집합체로서 코드로 국한된 단위였다.하지만 구조체와 같이 데이터를 정의하고 관리하는 문법과는 별개로 사용되었기 때문에 어떤 정보를 표현함에 있어서 일관성이 떨어졌다.
  • C++에서는 정보의 독립성과 일관성을 유지할 수 있도록, 데이터를 정의하는 구조체 나 해당 구조체를 사용하는 함수를 하나로 표현 할 수 있도록 하였다. 이것을 객체(Object)라고 하며 C++ 에서는 클래스(Class)라는 문법으로 제공된다.
  • 객체 (Object) 데이터와 함수를 하나로 묶어서
  • 클래스 (Class) 데이터와 함수를 하나로 묶어서
  • 용어
    인터페이스(Interface Function): 어떻게 구현했는지 잘 알지 못해도 그 기능을 사용할 수 있도록 제공되는 함수. 내가 실제로 동작하는 방법은 몰라도 작동할 수 있는 것. 버튼.
    메소드(Method Function): 클래스 내부에서 사용되는 함수. 객체 안에서 이뤄지는 행위. 자판기에서 돈 넣고
    멤버 데이터(Member Data): 객체 내부 데이터. 커피, 프림, 설탕…
  • 커피를 타는 일에 C와 C++을 비교해보자
직접 탐 커피자판기
C C++
행위와 데이터가 별개

바리스타의 능력에 따라

일관적이지 못함

데이터와 데이터를 사용하는 사람들을 묶어둠 일괄적으로 프로그램 대량생산 자판기를 어떻게 만들고 디자인해야 좋은 자판기가 되는지

 

클래스의 구조

  • C로 만든 코드
    struct People
    {
        char name[10];
        int age;
        double height; }; // 구조체
    
    void AddPeople(People *p)
    {
        scanf("%s”, p->name);
        scanf("%d“, &p->age);
        scanf("%lf", &p->height); 
    }
    
    void main() 
    {
        struct People data;
        AddPeople(&data); } // 함수
    
    *** C에서는 변화가 예상되는 코드는 미리 함수로 짜놓음

 

  • [C >>> C++]
    *** 포인터가 없어짐 
    class People 
    { 
    private:
        char name[10];
        int age;
        double height;
    public:
        void AddPeople()
        {
          scanf("%s", name);
          scanf("%d", &age);
          scanf("%lf", &height);
        }
    }; 
    
    void main() 
    {    
        People data;
        data.AddPeople(); 
    }

 

 

클래스의 구조

  • class Student // 클래스명 
    { 
    private: // 접근 제한자    
        int age; // 멤버 변수 
    public: // 접근 제한자
        Student() // 객체 생성자
        {
          age = 0;
        }
        ~Student() // 객체 파괴자
        {
        }
        void SetAge(int a) // 인터페이스
        {
          age = a;
        }
        int GetAge() // 인터페이스
        {
          return age;
        } // 멤버 함수
     };
  • 클래스명 : 구조체
  • 접근제한자 : 데이터 멤버 변수는 반드시 private에. 그래야 객체지향임.
  • 멤버 변수 : 자판기 안에 프림. 멤버변수만 사이즈에 들어감.
  • 멤버 함수 : 객체 안 작업하는 것들
  • 객체 생성자 : 자동호출. 편리하게 쓸 수 있는 이유. 자동초기화기능. 클래스 안에 클래스가 또 있다?
  • 객체 파괴자 : 클래스가 종결될 때 뒷처리.
  • 인터페이스 : Public에 들어가 있음. Private이라서 밖에서 접근을 못하니까 인터페이스로 외부에서 값을 넣을 수 있는 통로를 만들어주는 것

 

 

객체 생성자

  • 클래스와 동일한 이름을 가진 함수
  • 객체가 생성될 때 자동으로 호출
  • 클래스 내의 멤버 변수를 초기화 해주는 함수
  • 인자만 다른 동일한 이름의 함수가 여러 개 존재 가능
  • 생략 가능
  • 함수의 반환형 존재 X
  • class Student 
    { 
    private:
        int age; 
    public:
        Student()
        {
          age = 0;
        }
        Student(int a)
        }
          age = a;
        }
    }; 
    
    *** s data; 객체를 instance 
    (C++에서만 쓰는 용어. 눈으로 보기에는 한 개지만 객체 생성자도 호출하기 때문에 행위는 두 번 일어나는 것. 
    C에는 변수를 선언. 메모리 할당. allocation 한다고 함.) 
    Student() 호출 
    *** s data(1); 자신이 원하는 객체 생성자 호출. Student(int a)

 

객체 파괴자 (Object Destructor)

  • 생성되었던 객체가 더 이상 사용되지 않을 때 호출되는 함수
  • 클래스 명 앞에 ~가 붙은 이름을 가진다
  • 인자가 없는 단 하나의 객체 파괴자만 가질 수 있다
  • 객체가 파괴되는 행위는 암시적으로 일어나는 행위이므로 인자를 넘겨줄 수가 없음
    >>> 안만들거나 1개만 만들 수 있다
  • 생략 가능
    class Student{ 
    private:
        int age; 
    public:
        ~Student();
        Student::~ Student() // :: 함수가 길어지면 밖으로 뺌 
        }
           printf("End"); 
    }

     

TIPS C언어 강의노트 5. 구조체, 공용체

구조체

  • 서로 다른 데이터 형을 하나의 데이터로 군집화하여 사용할 수 있도록 하는 사용자 정의 데이터형
    c.f. 배열은 같은 데이터형끼리만 묶을 수 있음
  • struct 키워드와 사용 할 구조체 명을 명시하여 구조체 정의
  • 구조체 내부를 구성하는 데이터는 미리 정의된 데이터 형으로 선언해야한다
  • 구조체 내부의 각 데이터는 분리자(;)로 구분해야 한다
구조 

struct 구조체명 {
   데이터 형 변수명1;
   데이터 형 변수명2;
};
예제 

struct People {
   char name[10];
   int age;
   double height; 
};
구조체를 한번만 선언해서 사용하는 경우 구조체명 생략 
>>> 잘못된 것이 아님

struct{
   char name[10];
   int age;
   double height;
} data;

 typedef

  • 전처리기가 아님. 새로운 데이터 타입 만드는 것
  • 기존의 데이터 형을 새로운 이름으로 재 정의하는 사용자 정의 데이터
    typedef 기존 데이터형 새로운 데이터형;

    e.g.
    
     typedef unsigned int UINT;
     typedef int* INTPTR
  • 왜쓰는가?
    이름을 짧게 적을 수 있음
    어떤 데이터가 타입이 확실하지가 않으면 나중에 수정하기 용이함
  • typedef VS define 
    
    // define을 쓰면 어떤 문제가 생기는 지 알아봅시다. 
    #define MY_PTR int* 
    typedef int* INTPTR; 
    void main()
    {
        int a = 2, b= 3;
        MY_PTR p1, p2; >>> int *p1, p2; //p2는 포인터가 아님
        INTPTR p3, p4; >>> int *p3, *p4;
        p1 = &a;
        p2 = &b; >>> compile error!
        p3 = &a;
        p4 = &b; 
    
    >>> 이 둘은 확실히 다른 문법임. 
    define은 전처리기로, 데이터 타입을 정의하는 문법이 아님
    
    ** define은 되는데 typedefine은 안되는 것도 존재: 
    데이터 타입만 치환 가능하고 상수는 치환 안됨

 

구조체 사용하기

  • 정의된 구조체는 struct 키워드와 구조체 명을 이용하여 기본 데이터형 변수를 선언하듯 선언
    // people 구조체를 이용하여 people형의 data 변수를 선언 
    
    struct People data;
  • C언어에서는 매번 구조체를 선언할 때마다 struct키워드를 명시해야 하므로 typedef 명령어를 사용하여 데이터형을 재정의할 수 있다
    typedef struct People PEOPLE; 
    PEOPLE data; // struct 키워드 안적어도 됨

    typedef와 struct를 함께 (구조체 정의 + 데이터형 재정의)

    typedef struct People{
       char name[10]
       int age;
       double height;   //  파란색은 구조체
    } PEOPLE;
  • 구조체 또한 데이터형이기 때문에 변수 선언시 배열, 포인터 문법을 그대로 사용 가능
    struct People data; // 일반 변수 
    struct People list[20] // 배열
    struct People *p; // 포인터
  • 구조체의 각 요소에는 “.”을 이용하여 접근 가능
    struct People data; 
    
    strcpy(data.name, "홍길동"); // strcpy: 데이터형 복사 data.age=20; 
    
    data.height=175.0;
    
    >>> People
홍길동
20
175.0
name
age
height

 

구조체 동적 할당

  • 구조체 크기의 메모리를 동적 할당하여 선언하고 사용하기
    PEOPLE *p = (PEOPLE *)malloc(sizeof(PEOPLE));
    strcpy((*p).name, “홍길동”); // 연산자 우선순위 때문에 일일히 괄호를 써 주어야 함
    (*p).age = 20;
    (*p).height = 175.0;
    
    제목 없는 그림
  • ‘*’ 연산자의 우선순위보다 ‘.’가 더 높기 때문에 반드시 괄호를 사용해야 하는데 이와 같은 불편함을 줄여주기 위하여 ‘->’ 라는 약식 표현법이 제공
    strcpy(p->name, “홍길동");
    p->age = 20;
    p->height = 175.0;

 구조체 크기와 메모리 배열

  • 구조체 크기는 일반적으로 구조체를 구성하는 요소들의 데이터 형의 크기를 합산한 값
  • Visual C/C++에서는 처리의 수행능력을 높이기 위해 Structure Member Alignment를 사용하기 때문에 구조체 선언시 데이터형을 어떻게 배열했는 지에 따라 구조체의 크기가 달라질 수 있음
  • 구조체를 효과적으로 선언하려면 동일한 데이터형을 가진 변수끼리 모으고 작은 크기의 데이터형이 위쪽에 오도록 선언하면메모리 낭비를 줄일 수 있다
    struct MyData{
        char a;
        int b;
        short int c;
        int d;
     };
    sizeof(MyData)
  •  1byte 정렬시 = 11byte
    a b c d
    1 4 2 4
  • 2byte 정렬시 = 12byte
    a b c d
    2 4 2 4

제목 없는 그림

  • 구조체 크기는 눈으로 계산하지 말고 sizeof 연산자 써서

 

공용체

  • 공용체는 union이라는 키워드를 사용하며 구조체와 매우 유사한 형식
  • 구조체는 구조체 내에 선언된 변수들이 별도로 메모리를 차지하지만, 공용체는 가장 큰 변수의크기로 메모리가 할당
  • 공용체에 선언된 모든 변수들이 가장 큰 하나의 메모리 영역을 공유
  • 공용체 내에 선언된 모든 변수들은 할당된 메모리를 각자의 데이터 형으로 접근하여 사용
  • 어떤 때 사용?
    4byte를 3가지로 사용할 수 있음
    동일한 데이터를 여러가지 관점으로 볼 수 있음
    메모리를 아껴야 할 때

    union Friend {
       char a;
       short int b;
       int c; 
    };
    제목 없는 그림.png

 

공용체 사용

  • 공용체는 각 변수들이 동일한 메모리에 접근하기 때문에 한 변수의 값을 변경하게 되면 다른 변수의 값도 변하게 된다
    union Type{
        int i;
        short int s[2];
        char c[4] 
    }; 
    
    void main() 
    {
        union Type data;
        data.i=0x12345678;
        data.s[1]=0xABCD 
    }
    제목 없는 그림
    
    

TIPS C언어 강의노트 4. 다차원 배열, 포인터, 메모리 동적 할당

2차원 배열

  • 배열은 [] 를 사용하여 연속적인 메모리를 논리적으로 여러 개의 묶음으로 나눌 수 있다. [] 개수가 증가할 때마다 한 차원씩 증가한다
  • 2자원 배열 >>> 1차원 배열을 두개의 묶음으로 나눈 것
    int data1[19];
    int data2[19];

    >>> int data [19][19];
    >>> 1차원 배열을 묶은 것
  • e.g.

제목 없는 그림.png

  • 바둑판 생각하면 쉬움
  • 2차원은 축이 2개 (x, y)
  • 기계어 레벨에서는 1차원
  • data[1][0] = data[0][5]
    사람 입장에서는 x, y 순이 더 편하나, 컴퓨터는 반대
    1 2 3 4
    5 6 7 8   >>>> 1 2 3 4 5 6 7 8
  • Char data [2][3]   y, x
    _ _ _   _ _ _
    data[0] data[1]
    >>> x단위로 그룹 지어짐
  • Char data [3][2]   x, y
    _ _   _ _   _ _
    >>> 비효율적
  • Char data [4][5] = char data [20]

>>> 차원 계산은 2차원 사용보다 계산하여 1차원 사용하는 것이 더 좋음

  • 2차원 >>> 1차원
  • 1차원 >>> 2차원 몫과 나머지로
  • e.g. 
    
    char data [m][n] 
    data [a][b] 
    ax+b 
    a= index/n 
    b= index%n

 

2차원 포인터

  • 한 차원 높은 포인터가 한 차원 낮은 포인터를 가리킬 수 있음
  • *를 이용하여 한 차원 더 높은 포인터를 선언 할 수 있으며, *개수가 증가할 때 마다 한 차원씩 증가
  • 2차원 포인터는 1차원 포인터를 가리킬 수 있으며, 1차원 포인터는 차원이 없는 일반 변수를 가리킬 수 있음
  • p: 포인터 자신의 값
    *p: 가리키는 대상
    **P: 가리키는 대상의 대상
  • 맨 마지막 포인터만 4byte 하고 앞쪽은 일반 변수 해도 됨
    e.g 
    
    int data = 3;
    int *p = &data; // data 변수의 주소를 가지는 1차원 포인터
    int **pp = &p; // 1차원 포인터의 주소를 가지는 2차원 포인터
    
    제목 없는 그림

메모리 관련 키워드

  • Size of 연산자
    : 변수 또는 데이터 형의 크기를 byte 단위로 얻고 싶을 때 사용

    int data, array[5];
    printf("%d, %d, %d", sizeof(int), sizeof(data)sizeof(array));
    
    >>> 4, 4, 20 
    
    *** size of(array+0)은 연산으로 들어가서 20byte아니고 4byte
  • Casting
    : 강제적으로 데이터의 타입을 다른 타입으로 변환할 때 사용

    char data = 10;
    int num = 650;
    num = data; // 자동 형변환
    data=num; // 데이터 손실이 발생!! 
    
    >>> 
    
    // 강제 형변환 
    data=(char*)num;

 

메모리 동적 할당 

지역 변수의 한계성

* Stack에 저장되기 때문에 선언 할 수 있는 메모리의 크기가 제한 (지역 변수로 쓸 수 있는 메모리가 1mb. 힙은 통상적으로 2gb)
* 지역 변수는 사용여부와 관계 없이 자신이 선언된 함수가 종료될 때 까지 메모리 점유 
* 지역 변수의 메모리 크기를 변경하려면 해당 프로그램을 재컴파일 (컴파일 할 때 이미 스택 구조는 fix)

>>> 메모리 동적 할당: 포인터를 이용하여 실행 중 가변적인 크기의 메모리를 할당하고 해제
  • 메모리 해제
    void free (void *membolck); 
    ** membolck : 동적 할당된 메모리 주소
    
    * malloc - free는 쌍으로 사용
    * 사용을 완료하면 free함수를 이용하여 반드시 메모리 해제 (메모리 반환)
  • 메모리 동적 할당
    void *malloc (size_t size); 
    ** void: 할당된 메모리 주소 
    ** size: 할당할 메모리 크기
    
    * malloc(memory allocation) 함수는 할당된 메모리의 주소 값을 반환할 때 
      “정해진 변위가 없다”는 의미로 void * 형을 반환 
      >>> 포인터 변수로 주소를 받을 때에는 캐스팅
    * void 포인터 사용: 내가 가리키는 대상의 주소는 알고 있지만, 
      사용 할 범위는 정해져있지 않다
  • 함수가 정의된 헤더파일
    #include <stdlib.h> // malloc.h 혹은 memory.h
  • Short *p[3] >>> 배열이 우선 >>> 12byte포인터를 여러 개 선언
  • Short(*p)[3] >>> 가리키는 대상이 short*3=2*3=6byte 여기서 2byte씩 씀. 6byte 한번에 쓰는게 아니라
  • 지금까지는 stack (컴파일러가 만드는 메모리)
  • Stack : 맨 밑에 깔린게 가장 오래됨. First in last out
    SP
    BP+2
    BP+1
    BP(Base Point)

    ** Stack frame: 메모리가 어떻게 쓰이는지. 중간에 빈 공간이 없음. 순차적 관리.

  • Heap 에 할당된 메모리는 Stack에 할당된 메모리와 다르게 스스로 해제되지 않음
    e.g. 
    
    // Heap 영역에 1Byte 만큼의 메모리 공간을 확보하고,
    // 시작 주소를 char* 타입으로 변환하여 저장한다
    char *p = (char*)malloc(1);  
    free(p);  // 할당한 메모리를 해제한다
  • 동적 할당시 하나의 데이터형을 저장할 수 있는 크기가 아닌 배열처럼 여러 개의 데이터 형을 저장할 수 있는 크기의 메모리도 할당 가능
    e.g. 
    
    int i;
    char*p1, *p2;  
    p1 = (char *)malloc(sizeof(char)); // char크기만큼의 메모리 할당
    p2 = (char *)malloc(sizeof(char) * 5); // 5개의 항목을 가진 char 배열 크기 만큼의 메모리 할당
    
    *p1=0;
    for(i=0; i<5; i++) *(p2 + i) = i;
    
    
    제목 없는 그림.png
    char *p1 = (char *)malloc(sizeof(char)*2);
    short int *p2 = (short int *)malloc(sizeof(short int)*2);
    int *p3 = (int *)malloc(sizeof(int)*2), i; 
    
    for(i=0; i<2; i++){
        *(p1 + i) = i + 1;
        *(p2 + i) = i + 1;
        *(p3 + i) = i + 1;
     }
    
    제목 없는 그림
  • Heap의 조각시 메모리가 비효율적으로 돌아가 느려짐
    >>> 메모리의 압박이 없을 경우에는 제일 큰 값으로 일괄적으로 할당하는 것이 좋음
  • 배열에서는 상수만 적을 수 있지만, 메모리 동적 할당은 상수 말고 변수도 쓸 수 있음. 재컴파일 없이도 원하는 크기 세팅 가능
  • 노란 색은 스택, 파란 색은 힙
  • 포인터는 그림을 그려야 효과적으로 이해할 수 있음

 

동적할당의 장점

  • 지역 변수의 한계를 보완
  • Stack에 저장되기 때문에 선언할 수 있는 메모리의 크기가 제한된다
    >>> 할당한 메모리가 Heap 영역에 저장되기 때문에 Stack보다 더 큰 크기의 메모리를 할당할 수 있다
  • 지역 변수는 사용 여부와 상관없이 자신이 선언된 함수가 종료될 때 까지 메모리를 점유한다
    >>> 메모리의 사용 시점과 소멸 시점을 정할 수 있다
  • 지역 변수의 메모리 크기를 변경하려면 해당 프로그램을 재컴파일
    >>> 실행 중에 사용할 메모리의 크기를 정할 수 있다
  • 정적 메모리와 장단점 반대 >>> 상황에 맞춰서

 

메모리 동적 할당 예제

  • void main()
    {
    int *p, count, sum = 0, i;
    printf("숫자의 개수를 입력 : ");
    scanf("%d", &count);
    p = (int *)malloc(sizeof(int)*count); 
    
    for(i = 0; i < count; i++){
       printf("%d번째 숫자 입력 : ", i+1);
       
       sum = sum + p[i];
       }
    
    printf("입력 받은 숫자의 총합은 %d\n", sum);
    free(p); 
    }
    
    >>> 출력 결과 
    숫자의 개수를 입력 : 3 
    1번째 숫자 입력: 4 
    2번째 숫자 입력: 7 
    3번째 숫자 입력: 9 
    입력 받은 숫자의 총합은 : 20
  • 예외처리를 너무 많이 하면 문제가 있는데도 불구하고 프로그램 느려지면서 죽지않으면서 버팀

 

2차원 구조를 포인터로 어떻게?

  • 직접적인형태의 메모리 할당 (x)
int *p= (int *)malloc(sizeof(int) * 5);
int **pp = &p;
free(p);

제목 없는 그림.png
  • 배열 포인터를 이용한 메모리 할당 (x. 포인터 3개. 절반만 동적할당됨)
int*p_data[3], i;
for(i = 0; i< 3; i++){
   p_data[i] = (int *)malloc(sizeof(int) * 5);
}

for(i = 0; i< 3; i++){
free(p_data[i]);

제목 없는 그림.png
  • 2차원 형식의 메모리 구조로 동적 할당
int **pp = (int **)malloc(sizeof(int *)*3), i;
for(i = 0; i< 3; i++){
   *(pp + 1) = (int *)malloc(sizeof(int)*5);
}
pp[1][2] = 5;
제목 없는 그림

** 배열을 포인터로 만드는 방법 >>> 치환해서

data[a][b];
//data[a] = A로 치환
A[b];
*(A+b);
*(data[a]+b);
*(*(data+a)+b)
  • 해제는 할당과 반대로
  • *** char **p할 때 p= (   ) malloc (   )라고 써도 됨

 

포인터 변수에 const 사용

  • Const : 이 변수는 바꾸면 안돼!
  • 총 3가지 사용
  • 포인터 실수 막으려고 const 쓰는 경우가 많음
  • const int *p 가리키는 대상 메모리는 바꿀 수 없다
  • int *const p 포인터 p가 가리키는 주소를 바꿀 수 없음
  • const int *const p = &data1; 포인터 변수 자체도 상수화 하고 포인터 변수가 가리키는 주소도 상수화
  • 데이터 앞에 const 키워드를 사용하는 경우
    >>> 포인터 변수가 가리키고 있는 변수의 값을 상수화

    e.g. 
    
    const int*p 
    int data = 11; 
    p = &data; 
    *p=4; // Error!!
  • 데이터형 뒤에 const 키워드를 사용하는 경우
    >>> 포인터 변수 자체를 상수화 시키는 것으로 포인터 변수가 초기화 후에 다른 주소 값을 갖지 못하게 된다

    e.g. 
    
    int data = 3, 
    num = 5; 
    int *const p = &data; 
    p = &num; // Error!!
  • 데이터 앞과 뒤에 모두 const 키워드를 사용하는 경우
    >>> 포인터 변수 자체도 상수화하고 포인터 변수가 가리키는 대상의 값도 상수화

    e.g. 
    int data1 = 3, data2 = 5; 
    const int *const p = &data1; 
    p= &data2; // Error!! 
    *p = 10; // Error!!

TIPS C언어 강의노트 3. 변수, 배열, 포인터

표준 입력 함수

scanf ( const char *format [ , argument ] ... );
           입력 형식          입력받을 변수 
* scanf 함수 예제

int data = 0;
scanf("%d", &data);
char name[100];
scanf( "%s", name);
printf("당신의 이름은 %s 입니다.", name);
  • printf와 거의 유사함
  • 차이: printf는 %(키워드)와 뒤에 오는 변수가 타입이 일치하지 않아도 되지만, scanf는 반드시 일치해야 함.

 

scanf 함수 사용시 주의할 점

1) 앞에 있는 포인터랑 뒤랑 맞아야 함
2) Rewind
3) 공백도 들어감

* scanf 함수를 잘못쓴 예시 코드
int num = 0;
while(1){
   printf("나이를 입력하세요:");
   scanf("%d", &num);
   if(num>0 && num <= 130){
      break;
   } else {
      printf("Incorrect Age!!");

** While(1) 은 무한 루프
  • 표준입력버퍼에서 먼저 저장한 후에 CPU로 들어감
    >>> 표준입력버퍼에 값이 남아있으면 계속 실패
  • 표준입력함수는 표준입력버퍼가 비어있는 상태에서만 적용. 사용자가 입력을 잘못할 경우 무한루프
* fflush(stdin)을 이용하여 위의 상황을 해결해보자
int num = 0;
while(1){
   printf("나이를 입력하세요 :");
   if(scanf("%d", &num) == 0 ){
      fflush(stdin);
      printf("Incorrect Age!!");
   } else {
      if(num>0 && num <= 130){
      break;
   } else {
      printf("Incorrect Age!!");
   }
}

** Stdin = standard in

 

  • Buffer: 속도 차이가 나는 두 장치의 차이를 완화시키는 메모리
  • 오류를 잡아 줘야함 : fflush는 최신버전에서 사용 불가
    >>> rewind : 초기화
  • 비교나 연산시 상수가 앞에 있는 것이 좋음
    e.g. 2 + 3 + I
  • gets 쓰면 무조건 문자열만 받음

 

변수의 종류

 

  • 지역변수(Local variable) : 함수 안에 선언. 함수와 생명 주기를 같이하며 Stack에 저장된다. 초기화하지 않을 경우 알 수 없는 값이 들어있다.
  • 전역변수(Global Variable) : 함수 밖에 선언. 어떤 함수에서도 다 쓸 수 있음. 프로그램과 생명 주기를 같이 하며 Data Segment에 저장된다. 초기화하지 않을 경우 0 으로 자동 초기화된다.
  • 서로 다른 공간에 변수가 존재함. 변수이름이 같아도 하나는 전역 변수 / 하나는 지역에 있으므로 충돌 X
  • 확실하게 구조화된 언어를 구사하려면 전역변수는 지양
  • 가까운 쪽, 지역변수 우선
  • 정적변수(Static Variable) : 특정 함수에서만 사용할 수 있는 전역변수
  • 정적 변수를 지역 변수로 선언하는 경우 처음 함수가 실행되었을 때 한번 변수가 초기화되고, 다음 호출 시에는 이전 변수 값을 유지한다.
    * 정적 변수 사용 예시
    
    void TotalSum(int num) 
    {
       static int sum = 0; 
       sum = sum + num;
       printf("1부터 %까지 합은 %d\n", num, sum);
    }
    void main() 
    {
       int i; 
       for(i=1; i<=5; i++) TotalSum(i);
  • 전역변수는 특별한 값을 명시하지 않아도 0이 들어가 있음. 처음부터 끝까지 쓸 수 있음.
  • Static을 함수 안에서도 쓸 수 있지만, 소스에서도 쓸 수 있다
  • 전역변수 보호용으로 쓰기도 함
  • 모듈설계시 다른 모듈과 충돌되어 문제가 되는 것을 막기 위해
    * 정적 변수를 전역 변수로 선언하는 경우:
    한 소스 파일 내에서만 전역 변수처럼 사용할 수 있다. 
    일반적으로 전역 변수를 선언하면 외부 함수뿐만 아니라 
    다른 소스 파일에서도 extern 키워드를 이용하여 참조할 수 있다. 
    e.g.)소스를 나누면 에러발생 
    >>> 한 쪽에는 extern 을 전역변수 앞에 써서 참조하게 만듦
    
    A.cpp
    // A.cpp에 전역 변수 선언
    int global_num = 5;
    
    B.cpp
    // A.cpp의 전역 변수 참조
    extern int global num;
    void main() 
    {
    int data = global num; 
    }
  • 상수 변수(Constant Variable):
    const 키워드: 변수의 값을 변경할 수 없도록 한다. 에러 검출 및 프로그래머의 실수 방지를 위해 사용할 뿐 상수 변수가 가진 값에 영향을 주지 않는다.
  • 따라서 >>> 적으나 안적으나 기계어에는 똑같음
  • 프로그래머가 소스 작성시 실수 줄여주기 위한 목적
    int data = 3; 
    if(data = 3){
       data = data + 2;
    }
    >>> No Error! No Warning!
    
    const int data = 3;
    if(data = 3){
       data = data + 2;
    }
    >>> error C2155: L-value specifies const object

 

 

변수가 메모리에 어떻게 올라가는지

  • 제목 없는 그림Stack frame은 언어끼리 호환이 안됨
  • 안드로이드가 느린 이유: C와 JAVA가 둘다 쓰여서 Stack Frame이 다른 것을 맞춰야 돼서

 

배열

 

  • 동일한 데이터 타입의 데이터를 유사한 목적으로 사용해야 할 때 해당 메모리들을 그룹지어 정의할 수 있는 문법
  • 원래는 Built-in 데이터 타입이 많았음. But 일일히 다 외울 수 없음. 사용자 정의 데이터 타입을 만드는 기술
  • e.g. 40byte >>> int data[10];
  • 왜 쓰는가?
    1) 너무 많으면 부르기 힘드니까
    2) 군집화된 기술을 쓰면 더 효과적인 표현과 관리가 용이
  • [ ] 에 필요한 데이터 개수 명시
  • 메모리에 연속적으로 할당
  • 배열의 인덱스는 [0]에서 [배열 항목수 – 1] 까지 이다
    >>> 인덱스 실수하면 다른 변수가 변할 수 있으므로 주의할 것.
    Debug mode에서 되는데 Release mode에서 안되면 인덱스 문제일 가능성이 큼

    * 반복문을 같이 적용하면 좋음
    
    int data[10];
    data[0] = 1;
    data[1] = 2;
    ...
    data[9] = 10;
    
    ▼▼▼▼▼▼▼
    
    int data[10], i;
    for(i=0; i<10; i++){
       data[i]=i+1;
    }
    * 배열의 초기화
    
    - 배열의 선언과 동시에 초기화 
    int num[5] = {0, 0, 0, 0, 0}
    - 자동 초기화 
    int num[5] = {0, }; // int num[5] = {0};과 동일
    int data[10] = {1, 2, 3, };
    
    ** 대부분의 군집명령은 중괄호{} 씀
    ** ,찍고 공백이면 0으로 채워짐

 

문자열 관리

  • 문자가 아닌 문자열을 저장하기 위해서는 여러 개의 char 변수가 필요 이 것을 개별적인 변수로 처리하면 관리가 불편하기 때문에 배열을 사용하여 처리하는것이 일반적
  • e.g.
    Hi~ 라는 문장을 저장하려면 변수 3개를 선언해야하는 것(x)
    4개의 항목을 가진 char 배열을 선언하고 저장

    char string[4] = "Hi~"; >>> string 'H' 'i' '~' 0 
    
  • 이와 같이 문자열로 관리되기 때문에 문자열 처리를 위한 함수 제공
    strcpy(string "ABC"); 
    sprintf(string, “%3d”, 5);
  • 문자열은 끝에 0이 들어감
  • sprintf = spring printf.
  • strcpy는 느리므로 익숙해지면 memcpy (memorycopy)

 

포인터(간접주소지정방식)

  • 변수의 값을 변경하려면 해당 변수의 이름으로 접근해야 하지만 포인터를 사용하면 해당 변수의 주소를 가지고도 접근 가능
  • 주소를 사용하여 다른 변수에 접근하는 특별한 능력을 가진 변수
  • 포인터 변수 선언 시 *를 사용하여 일반 변수와 구별
  • 다른 변수의 주소를 알아낼 때는 &를 사용한다
  • 포인터가 가지고 있는 주소에 접근 할 때에도 * 사용
    * 포인터 사용 예시
    int data = 5: 
    int *p = &data; 
    *p=3; //data 가 3으로 바뀜
  • 포인터가 가진 기본적인 특성을 이해하면 그 힘이 커짐
  • 포인터 변수 : 자기 자신도 쓸 수 있고/ 주소에 가서도
  • 주소를 알아내는 방법 : &
  • p=5;
    >>> p에 5를 넣겠다. 번지. 주소에
  • *p=5;
    >>> p가 가리키는 주소에 가서 5를 대입. 5번지에 가서 5를 대입
  • C언어 자체가 아닌, 기계어에서 적용되는 기술
  • 포인터는 잘못쓰면 죽음
  • 포인터는 무조건 4byte
  • 포인터 앞에 써있는 int는 포인트의 대상 메모리의 실제 유효범위

 

포인터 변위

제목 없는 그림

  • Casting: 타입이 다를 때

제목 없는 그림.png

  • Byte 정렬 기술에 따라 다름
    cf; 리틀인디언 – 거꾸로 들어감 / 빅인디언
  • ndk : 안드로이드를 C로
  • 다른 문법과 함께 쓸 때 시너지
  • ! 죽음의 참조
    int *p; *p=5
    >>> 아무데나 5 대입

 

포인터와 배열의 표기법

  • 포인터와 배열은 표기법을 바꾸어 쓸 수 있음
    int data[5];
    data[2] = 10;
    
    ▼▲
    
    *(data+2)=10;
  • 포인터가 많이 써서 복잡해지면 배열 표기법으로 쓰면 깔끔해 질 수 있음
  • 배열의 이름은 배열의 시작 주소다?
    *100 >>> 100번지로 가라
    *&100 그 번지가 몇번지냐 >>> */ 같이쓰는 느낌

 

SWAP

void Swap(int parm1, int parm2) 
{
   int temp = parml; 
   parml = parm2; 
   parm2 = temp; 
}
void main() 
{
int num1 = 5, num2 = 3; 
printf("num1 = %d, num2 = %d\n", num1, num2); 
// 두 정수의 값을 맞바꾸는 Swap함수를 호출한다 
Swap(numl, num2); 
printf("num1 = %d, num2 = %d\n", num1, num2);

 

void Swap(int *p1, int *p2) 
{
   int temp = *p1; 
   *p1 = *p2; 
   *p2 = temp; 
}
void main() 
{
   int num1 = 5, num2 = 3; 
   printf("num1 = %d, num2 = %d\n", num1, num2); 
   // 두 정수의 값을 맞바꾸는 Swap 함수를 호출
   Swap(&num1, &num2); 
   print("num1=%d, num2=%d\n", num1, num2);
}
>>> 출력 결과
num1=5, num2=3
num1=3, num2=5

* Pointer을 사용하면 함수의 원형은 지키면서 다른 함수에 있는 지역변수를 바꿀 수 있음

TIPS C언어 강의노트 2. 반복문, 함수, 프로그램 생성

반복문

  • 문장을 반복하여 수행할 때 사용하는 문법
  • 조건문은 1 실행하는 반면, 반복문은 까지 계속 반복
  • 컴퓨터는 명시적으로 명령을 내려야
  • 반복의 3요소
    1) 시작조건
    2)
    종결조건
    3)
    조건 변화식
  • >>> 하나만 안해도 무한반복을 하거나 반복하지 않음

 

for(시작조건; 종결조건; 조건 변화식)

• for문의 동작 흐름 
for( 시작조건; 종결조건 ; 조건 변화식 )
"종결조건" 만족 시 수행할 명령문
시작조건 •> 종결 조건(T) •> 명령문 •> 조건 변화식 •> 종결조건(T) 
•> 명령문 -> 조건 변화식 •> 종결조건(F) >>> for문 종료
  • 코드가 제일 간단
  • 반복의 3요소 모두 갖춰짐

 

While

• while문의 동작 흐름 
시작조건 
while(종결조건){ 
“종결조건"에 만족 시 수행할 명령문 
조건 변화식 
}
  • For 유사함. But 차이는 for 조건이 정형화 / while 조건이 변칙될
    그러나 차이는 없으므로 편한 쓰면
  • If문과 형태가 유사
  • 거짓이 때까지 계속 반복

 

Do~while

do ~ while 반복문의 동작 흐름 
시작조건 
do{ 
"종결조건”에 만족 시 수행할 명령문 
조건 변화식 
} while(종결조건};
  • do—while문은 최소 1 번의 실행은 보장된다
  • While과의 차이. Do while 해놓고 생각함. 한번은 수행함. 한편 while 조건이 맞지 않으면 한번도 수행하지 않을 있음.
  • 일이 거의 없음

 

반복문 예제

제목 없는 그림

  • 1+2+3+4+5
  • 반복문 무엇을 고민하지 마라

 

***go to???***

가능하면 쓰지

구조화를 깨기 때문에

그러나 있는 이유는? 스파게티 랭귀지에 익숙해진 시장 상황에서 Structured language C언어 사용을 장려하기 위해.

한마디로 무시할

코드의 중복을 줄이자

int sum = O, i; 
// 1~5 까지 합산
for(i=1; i<=5; i++){
  sum = sum + i; 
}
sum = O; 
// 1~10까지의 합산 
for(i=1; i<=10; i++){ 
  sum = sum + i; 
}
sum = O; 
//7~15까지의 합산
for(i=7; i<=15; i++){ 
  sum = sum + i; 
}
for(i=a; i<=b; i++){ 
 sum = sum + i; 
}
  • 좋은 프로그래머
    1) 조건문 적게 사용
    2) 중복된 코드가 적어야
  • 먼저 무엇이 중복된 것인지 특징을 잡아내야
  • 함수로 줄일 있다

 

함수

제목 없는 그림

*** 함수를 사용하여 코드를 줄인 결과 ***
int sum = O, i; 
// 1~5 까지 합산
for(i=1; i<=5; i++){
  sum = sum + i; 
}
sum = O; 
// 1~10까지의 합산 
for(i=1; i<=10; i++){ 
  sum = sum + i; 
}
sum = O; 
//7~15까지의 합산
for(i=7; i<=15; i++){ 
  sum = sum + i; 
}
int sum = O, i; 
// 1~5까지의 합산
 sum = Total(l, 5); 
 // 1~10까지의 합산
 sum = Total(l, 10); 
 // 7~15까지의 합산
 sum = Total(7, 15);
  • 2개의 매개 변수. 개의 반환형
  • 함수는 대문자 시작, 변수는 소문자 시작
  • Header = functional prototype 함수의 원형
  • Return : 시점에서 함수를 종결하겠다 | 함수의 최종값을 반환하겠다
    Return 뒤로는 수행되지 않음
    *** R
    eturn XXX : XXX 함수의 최종 마무리
  • 함수에서 int 생략할 있음
  • Void: 반환값이 정해져 있지 않다 >>> 반환값이 없다
    >>> return 함께 없음
  • 함수를 사용하면 >>>
    1)
    코드의 단순화
    2) 대처가 용이하다
    3) 코드의 재사용이 가능하다
  • 매개변수(Parameter) : 함수를 사용하는 곳에서부터 처리할 데이터를 넘겨받아 호출된 함수내부에서 사용할 수 있도록 하는 지역 변수
  • c.f. argument

  • 함수의 이름은 영문자(a~z, A-Z) 숫자(0~9) underbar(_) 을 사용한다
  • 함수 네이밍 중요함. 함수가 많으므로 이름만 봐도 어떤 기능인지 유추하거나 검색할 있게끔
    >>> 내가 아는 단어다 하고 넘길 것이 아니라 단어도 일종의 표준화된 약속이므로 확실하게 익히고 넘어갈
  • 함수의 반환형 : 함수가 특정 작업을 하고 나서 함수를 호출한 곳으로 작업 결과를 알려줄 필요가 있을 때 return 키워드를 사용하여 한가지 데이터를 반환할 수 있음. (생략 int 형으로 간주됨)

 

Void 반환형

  • “정해져 있지 않다”
  • 따라서 void 반환값을 가지는 함수에서는 return문 사용시 값을 명시하면 안됨
void Set Data(double data) 
{
  double temp = data; 
  return;
}

main 함수

  • C언어로 작성된 프로그램은 함수의 집합체. 함수는 프로그래머에 의해서 임의로 만들어 질 수 있기 때문에 어떤 함수가 프로그램의 시작이 되는지 약속되어야 함.
  • C언어에서는 시작 함수로서 main 함수를 정의해야하며 반드시 한개만 존재.
  • 과거의 언어들은 위부터 순차적으로 진행되었으나, C언어는 함수를 기준으로 실행됨. 함수가 함수 호출
  • 사용자가 조작할 있는 함수가 아님
  • 1 반환: 성공적으로 반환 / 오류가 1

Caller Callee = 호출자와 피호출자

제목 없는 그림

  • Callee Caller보다 일반적으로 위에 있음. 그래야 누가 불렀는지 알기 때문에.
  • 함수의 원형: 함수의 이름, 매개 변수
  • Stack frame: 실제 함수가 호출 되었을 어떻게 메모리가 변하는지

 

프로그램 생성과정

제목 없는 그림

  • 컴파일 + 링크 = 메이크
  • 통상적으로 Compile하면 실행파일까지 만드는 것으로
  • 소스에서 바로 실행파일 만들고 목적파일(*obj) 만드는 이유: 완충효과. 변화대응. 분할이 가능해서 소스가 길어질 경우 효율성을 증대시켜 컴파일이 빨라짐. 보안
  • Object 단점: 모든 소스가 들어감
  • library: 실행한 것만.
  • .h (header) 함수의 원형만. lib, obj 같이 제공

 

전처리기(Pre-processor)

  • 프로그래머가 컴파일러에게 명령을 지시하는
  • 컴파일러 지시기
  • 전처리기는 #으로 시작하고 끝에 ; 사용하지 않는다.
  • include 전처리기
  • #include “stdio.h” : 현재 working directory에서 찾겠다. 사용자가 만든 헤더파일. 꺽쇠도 포함
  • #include <stdio.h> : 꺽쇠는 경로. 시스템이 제공하는 거면
  • Standard input output

 

표준 입출력 함수

  • 데이터를 모니터에 입출력할 수 있는 기능을 제공해주는 표준함수 및 라이브러리 함수
  • 콘솔: 모니터를 쓰는 시스템 >>> 콘솔 입출력 함수는 현재 거의 안씀
  • 다양한 시스템에서 사용할 있는 것은 표준 입출력

 

표준 출력 함수

printf( const char *format  [, argument] … );

                     출력 형식                    출력할 변수

키워드

%d

%f

%lf

%c / %C

%s / %S

데이터형

//decimal

int

float

//long float

double

char

c : 아스키 코드

C: multibyte. 다국어 지원

UTF-8, 유니코드

//string. 문자열

Char[] (char*)

키워드

%u

%x / %X

%o

%e

%p / %P

데이터형

unsigned int

//hexadecimal

16진수

//octa

8진수

//exponential

지수형 실수

메모리 주소

제목 없는 그림

  • Printf에서 f는? Format. 형식화된 출력
  • 뒤에 오는 변수보다 키워드 중요함
  • % print f 함수가 제공하는 문법. 쌍을 맞춰야

 

표준 출력 함수제어 코드

\n : 개행 (다음 라인으로 커서 이동) 
\r : carrot(깜박이는 커서) return. 해당 라인의 가장 앞쪽으로 커서 이동 
\a : “삑” 하는 비프음 발생 
\b : 직전의 문자를 지운다.(Backspace) 
\t : 수평 방향으로 하나의 탭만큼 커서 이동 
\' : 작은 따음표 출력 
\" : 큰 따음표 출력 
\\ : 원 표시(₩) 출력
  • Stdio에서 제공하는
  • Printf 제공하지 않음
  • 백슬래시
  • \n: line. 언어마다 다르므로 상황에 따라 써야함
  • “\” abc \”” >>> “abc” 출력
  • %% >>> % 출력

 

표준 출력 함수 – 출력 형식화

제목 없는 그림.png

  • 중요한 계기판은 아날로그로 해야 직관적으로 인지함
  • 출력 형식화: 디지털적 숫자에서 범위를 인지할 있도록 하기 위해
  • 좌우 정렬이 아니라
  • . 자리수에 포함
  • 반올림됨 >>> 실수 오차가 커질 있으므로 신경 써야함

TIPS C언어 강의노트 2. 연산자 / 조건문

연산자(Operator)

  • 모든 프로그래머가 원하는 개별적인 연산을 지정할 때 사용하는 식별자
  • + – * / … etc

 

정수 연산의 특성

  • 수학에서는 연산자 우선순위만 존재, but, 컴퓨터의 정수 연산은 연산 방향도 중요한 요소
  • 앞 -> 뒤 (2*3)/4=1
  • 뒤 -> 앞 2*(3/4)=0
    >>> 앞에서 뒤로 할 지, 뒤에서 앞으로 할 지 연산 방향에 대해 설정해 주어야 함
  • 그러나 대부분 앞에서 뒤이므로, 뒤에서 앞에서인 경우만 주의하면 됨
  • 기억이 잘 안나면 괄호를 쓰면 됨

 

나머지 연산자 (%)

  • 사칙연산자 + 나머지 연산자(%)
  • i = (i+1)%10; (0~9까지 나머지) I값은 0 ~ 9 값을 벗어날 수 없다
  • 프로그램은 수식이나 연산을 활용하여 조건문을 최소화하는 것이 좋음. 효율이 떨어짐.
  • I = (i-1)%10; >>> (x) 음수가 나오므로 나머지를 출력할 수 없음
    i=(10+i-1)%10 >>> 나머지는 10을 더해도 값이 같으므로

증감 연산자 (++, –)

  • I = I+1; // i값을 1증가. ADD 명령어로 번역
  • i++; // i값을 1증가. INC 명령어로 번역 >>> 속도가 더 빠름
  • 전위형 (Prefix Expression, ++가 앞에. 자기값부터 연산),
    후위형(Postfix Expression, ++가 뒤에. 다른거 다 연산한 후에 자기값 연산)
  • Int result = 0, data=5; result=++data; 6 result=–data; 5
  • Int result=0, data=5; result=data++; 5 result=data–; 6
  • 이런 경우 컴파일러가 알아서 조정해 주기 때문에, +연산자가 better

 

관계식

  • 조건 판단시 0만 거짓이고, 0을 제외한 모든 값은 참
  • AND(&, &&) : 내 대상을 0으로 만듦 / 대상의 값이 무엇인지 확인(검출)
  • OR (|, ||): 둘 다 0일 때 0 / 대상을 1로 만들고 싶을 때
  • XOR(^)(exclusive 배타적 논리합) : 서로 같으면 0, 다르면 1 / 암호화할 때
  • NOT(~, !): 값을 반전시킴.
  • (bit연산자, 관계연산자)= (bit단위 계산, 참거짓판별)

 

관계연산자

  • && – AND (논리곱)
  • || – OR(논리합)
  • ! – NOT(논리 부정)

 

진법변환

2진법을 16진법으로 변환하는 방법

  • C언어는 3가지 진법 지원 (C언어는 2진법 지원 안함)
  • 010 : 8진법
  • 10 : 10진법
  • 0x10 : 16진법 >>> Bit패턴 파악 용이. 4bit
  • 진법변환 TIP!: 1, 2, 4, 8 기억해서 조합
  • Bit pattern 바꾸는건 4bit씩 나눠서

 

쉬프트 연산자 (>> <<)

>, <<) 쉬프트(Shi[t)연산자는데이터를 비트 단위로 이동시켜 값을 증감시기 는 연산자입 니다. 데이터 << 이동할 비트 수 54

  • 데이터를 비트단위로 이동시켜 값을 증감시키는 연산자
  • 속도를 빠르게
  • 2의 승수를 곱하거나 나눌 때 씀. X * 3 이런건 불가
  • X *100 = x * (64+32+4) = (x <<6) + (x<<5) + (x<<2)
  • 쉬프트 연산자가 +보다 연산우선순위가 낮으므로 주의해서 사용할 것

 

부호가 없는 경우

  • 데이터 >> 이동할 비트 수 40 >> 2 = 40/4 = 10

 

부호가 있는 경우

  • 데이터 >> 이동할 비트 수
  • -12>>1 = -12/2 = -6
  • 부호가 있는 경우에는 최상위 비트에 따라 달라짐. 최상위 비트가 1이면 1, 0이면 0
  • 복잡하므로 주로 쉬프트 연산자는 Signed일 땐 안씀

 

비트 연산자

 

  • 메모리 낭비를 줄이기 위해 변수의 최소단위인 bit단위로 값을 연산

 

 

배타적 논리합 연산

  • 0x1F를 암호키로 정해서 다시 풀면

 

조건문

  • 나에게 맞는 조건문을 써라. 컴파일러가 알아서 최적화해줌
  • Ex) Int num = -3; if(num<0)num=num*-1;
  • Ex) int num = -12; if(num<0){ num=num*-1; num=num%10; }
  • 조건문이 많으면 안됨
  • If문 뒤에 ;있으면 나중에 debugging할 때 찾기 어려움 if문 뒤에 {
  • Syntax (문법적 오류) / Symentax error (논리적 오류. bug)
  • = 대입 / == 같다

 

If~else 조건문

  • Int price = 1500; double point; if(price >1000) point = price*0.1; else point = price*0.05;
  • Else문을 생략하면 if문

 

If~else if~else 조건문

  • 각 문은 상호배타적이어야 함
  • {} 복합문은 두개이상 연결될 때 쓰므로 생략 가능
  • If else의 중첩문. 새로운 문법이 아님
  • 조심할 것: 항상 참이 높은 확률의 조건문이 위에 있어야 함
  • Char score = 78, grade; if(score>90) grade = ‘A’; else if(score>80) grade = ‘B’; else grade = ‘C’;

 

Switch 조건문

  • 구성이 복잡하므로 if문을 훨씬 많이 씀
  • Default는 if문의 else같은 역할
  • If문은 범위일 때 유리 / switch는 상수일 때 유리… 했으나 요즘에는 컴파일러가 똑똑해서 상관없음
  • Ex) int num1 = 1, num2=3; char oper = ‘-‘; switch(oper){ case ‘+’: num1 += num2; break; case ‘-‘: num1-=num2; break; default: num1=0; }
  • If문으로 바꾸면? if(oper == ‘+’) num1 += num+; else if(oper == ‘-‘) num1-=num+; else num1=0;

TIPS C언어 강의노트 1. C언어 기초

  1. 프로그래밍을 시작하는 이에게

    익숙해지는 것 먼저 >>> 그 다음에 이해된다
    때문에 정독이 아닌 다독

    분명한 목표 설정을 해야 버틴다
    프로그래밍 문법을 배우는 것이아니다. 컴퓨터적 사고방식을 배우는 것.
    프로그래밍 공부는 혼자하지 마라. 팀으로 배울 때 더 많은 사고방식을 배울 수 있기 때문

    *** WHY C? ***
    Long Run Language
    C로 시작하면 다른 언어를 익히더라도 더 좋은 코드를 짤 수 있음
    쉬운 언어는 그만큼 유행도 빨리 변함
  2. C를 시작하기 위한 가장 기초적인 지식 Part 1

비트(bit) - 두 가지 중 한 가지 값을 저장할 수 있는 단위.

바이트(byte) - 8비트(bit)로 구성되는 정보 단위. 2의 8승으로 256종류의 정보를 나타냄

>>> 데이터의 값보다 데이터의 범위가 더 중요

 

32bit 운영체제 / 64bit 운영체제

일반적으로 프로그램은 32bit 기반

32bit 운영체제는 4gb ram까지 적용

 

Program => Data Structure(이미 정립 돼 있음) => Algorithm

알고리즘은 프로그램에 대한 사고방식을 내가 키우고 직접 만들어야 생길 수 있는 것(단순히 책보고 되는 것이 아님)

 

프로그램 언어의 구성요소

  • 시작과 끝이 있다
  • 사용자 입력이 가능해야 한다
  • 입력한 정보를 저장할 수 있어야 한다
  • 사용자에게 정보를 보여줄 수 있어야 한다
  • 연산할 수 있어야 한다
  • 조건에 따른 처리가 가능해야 한다
  • 반복적으로 수행할 수 있어야 한다

 

부호 _ _ _ _ _ _ _ _ 2*2*2*2*2*2*2=2^7 = 128

  • -가 없음 >>> 그럼 어떻게? >>> 최상위 비트를 부호 비트로 사용 >>> 0이면 양수, 1이면 음수 !!! 0이 없음. 0은 양수에 붙어있음. 왜? 더 효과적 0까지 처리하면 1비트가아님 2비트가 필요함

 

ASCII Code

  • 원래 Fax System
  • 문자 >>> 숫자
  • 표준

 

Data Type

  • 내가 쓸 데이터의 메모리가 어느정도 필요하는지?
  • 정수 2종류 / 실수 2종류
Char (Character)
      • 문자는 1byte에 저장하는 것이 좋음
      • 무조건 문자만 써야 하는 줄 아는데 아님. 0~255 사이 숫자면 저장 가능
부호 있음 부호 없음
Signed

 

Unsigned
-128~127

많이 쓰므로 생략가능

0~255
Int

(integer)

      • 정수
      • 4byte 메모리
      • 해당 System의 Bit를 따라감.
      • 일반적으로 32bit이므로 >>> 32bit
Short int Long int
64bit 32bit
Short (int)

 

생략 가능 * (long) int * long (int)
    • (Signed)
    • Unsigned
    • (Signed)
    • Unsigned
float
double 가능하면 이걸로 사용

단, 메모리가 부족하면 float으로

 

문장

  • 명령어를 처리하는 단위
  • 단일 문장 : 한 개의 명령어로 구성된 문장 ; (세미콜론)으로 구분 e.g. command;
  • 복합 문장 : 여러 개의 명령어로 구성된 문장 {} 중괄호로 범위 지어 표현 e.g. { command1; command2; }

 

변수 및 상수

 

숫자형 그냥 적고
문자형
문자열형 “”

 

변수 앞에는 데이터타입을 앞에 적기

Data type + 변수명

! 변수명은 소문자로, 연결은 _

善과 고구마: 나는 따뜻한 강자가 되고 싶다

  1. 막장 드라마에 비추어진 ‘善’의 모습

     지난 주에 말많고 탈많았던 내딸, 금사월(내딸 친구, 주오월)이 종영했다. 가열차게 시작했던 이 드라마는 금사월이라는 고구마역을 비롯한(실제로 금사월은 드라마에서 연인이었던 강찬빈에게마저 고구마라 불렸다.) 다채로운 이해 불가 캐릭터를 탄생시키며 새로운 주말 시트콤의 역사를 썼다.
    이 드라마를 보지 않은 사람들을 위해 주인공인 금사월이라는 인물에 대해 간략히(는 막장드라마 설정상 조금 어렵긴 하다) 설명하자면; 금사월은 신득예(전인화)와 오민호(박상원파크랜드)사이에서 태어난 딸로, 당연하게 그 둘 사이에서 자라지 않았으며, 친부모를 늦게 알게 된다. 그녀는 금빛보육원에서 금혜상과 주오월과 함께 자라게 되나, 금빛보육원은 강만후(손창민_신돈)가 이끄는 보금건설의 부실공사로 인해 무너지게 된다.

    금사월의 고구마적 특성의 1차 핵심은 악녀인 금혜상과 같은 집에서 살게 되면서 나타나게 되는데, 그녀는 언제나 답답하고 때론 멍청하게 당한다. 그리고 2번째 고구마적 특성은(이게 가장 화가 나지) 죽은 줄로 알고 있던 절친 주오월을 알게 된 이후에도 꾸준하게 친구의 이름을 이홍도라는 이름으로 부름으로써 주오월의 친부를 매우 늦게 찾도록 한 데에 기인한다. 3번째 고구마는(개연성 제로) 친모인 신득예가 금사월에게 친모임을 밝히면서 폭발하게 되는데, 그녀의 친모가 자신의 연인인 강찬빈과의 결혼을 망쳤다는 이유로 어머니가 그간 겪어왔던 악행(아버지 회사 남편 강만후에게 빼앗김 / 시어머니에 의해 치매인 어머니 사망 / 아버지를 몇십년간 정신병원에 감금 등)을 악으로 규정하며 증오하고, 악순환의 고리를 강찬빈(친모 신득예가 키운 강만후의 배다른 자식)과의 결혼으로 풀어보겠다는 말도안되는 선택을 의미한다.

    금사월을 이야기 한 것은 이시대 미디어가 그리는 ‘善’의 캐릭터를 가장 극단적으로 보여준 사례이기 때문이다.

    그럼, 다른 드라마는 다를까? 다르지 않다.

    이땅의 많은 드라마가 그리는 ‘善’은 답답하다. 주로 선악구도를 그리는 드라마에서(모든 드라마가 선악구도로 캐릭터를 선정하는 것은 아니다.) 선역이 악역에 대항하는 대표적인 방식은 ‘善’을 버리는 것이다. 한마디로, 흑화하는 것이다. 선하고 답답했던 캐릭터(주로 여성)이 악역에게 복수하는 방식은 새로 태어나는 것이다. 아내의 유혹에서 장서희가 점을 찍고 나타났듯. 그리고 현재 이유리가 열연중인 ‘천년의 약속’도 비슷한 설정으로 악역에 대한 복수를 강행하고 시청자들로 하여금 나름의 카타르시스를 선사한다. 이런 드라마에서 주는 선역들이 주는 사이다는 근본적으로 분노와 악에서 온다. (그맛으로 막장드라마를 보는 경우도 많다)

     

     

    2. 대장금이 그렸던 ‘善’ : ‘善’도 사이다를 줄 수 있다

내가 지난 방학 잉여기간동안 홀딱 빠져서 본 드라마, 대장금(2003)은 요즘 드라마에서 보기 힘들었던 善역의 이상향을 그려준다.

54부작이었던 대장금을 한회도 빠짐없이 몰입하면서 볼 수 있었던 힘. 주연 배우 이영애씨를 비롯한 배우들의 힘, 이병훈 감독의 연출, 궁중음식이 전하는 볼거리 등 여럿이 있었겠지만, 나는 극의 서사 전반이 그리는 ‘대장금’이라는 캐릭터가 전하는 메시지의 울림을 이야기하고자 한다.

한 인물의 영웅담을 극대화한 ‘대장금’이라는 드라마에서 장금이는 단연 선역의 면모를 제대로 보여준다. 언제나 그녀는 악역 최판술 상단 패거리가 깔아놓은 덫에서 위태로운 순간을 맞이한다. 온갖 산전수전 다겪는다. 그런데 그녀는 그런 거대한 악에서 특유의 열정과 재기, 그리고 휴머니즘으로 새로운 국면을 가져온다. 생각시 시절 쫓겨난 다재헌에서 포기한 사람들의 무기력에 굴하지 않고 끈질기게 새로운 약초를 키워내고 사람들을 다시 일으켜 세워 궁으로 돌아간다던가, 의녀가 된 후 악역 동료로 인해 역병마을에 같혔을 땐 그곳의 백성의 분노를 마음으로 감싸 혼신을 다해 치료하고 역병의 원인을 알아낸다.

그렇다고 해서 그녀가 복수의 마음을 품지 않은 것은 아니다. 최판술 상단 패거리의 모략으로 제주도 유배중 어머니같던 한상궁을 잃고, 내려간 제주에서 그녀는 복수의 마음으로 의술을 익힌다. ‘사람을 위하는 의술’과 ‘나와 내가 사랑하는 사람을 해한 그들에 대한 분노’사이에서 그녀는 갈등한다. 결론적으로 그녀는 그녀다운 방법으로 복수를 하며 의술과 분노의 딜레마를 푼다. 둘다 해낸다.

자신과 한상궁을 모함한 방식(임금의 병이 음식 때문이 아니라 진단의 오류인데 음식인 것으로 몰아져 역모로 내쫓김) 그대로 최상궁이 같은 위험에 취하게 되었다. 정황상 음식의 문제인 것이 확실시 되어가는 상황에서 그녀는 음식의 문제가 아님을 밝힌다. 같은 방식으로 최상궁을 골로 보낼 수 있었던 절호의 기회였는데도 말이다. 그 동안 그녀는 몇번이나 최상궁을 찾아가 최상궁의 삶을 감쌌던 두려움과 피해의식을 벗길 기회를 주려 한다. 그녀는 결단코 직접적으로 그들에게 음해를 가하는 법이 없었다. 그녀방식대로 그녀 자신이 지닌 선의 속성과 능동성을 끝까지 지켰다. 그러고도 가장 멋진 방식으로 복수했다.  대부분의 선역이 복수를 위해 자신을 버리고 선을 버리며 정당성을 취했던 것과는 사뭇 다르다.

3. 현실세계에서 그려지는 ‘善’의 그림자

현실세계에서 이젠, 더이상 ‘착하다는 것’이 좋은 것으로 통하지 않게 되었다. 착하다는것은 곧 만만한 것 내지는 답답한 것, 재미없는 것, 융통성 없는 것과 별다르지 않은 것이 되어버렸다. 그게 아니라면 최소한, 이 사회의 피라미드에 올라가기 위해서는 때로 선을 포기해야 할 순간도 생긴다고. 그렇게 알아가며 어른이 되었다. ‘善’과 ‘惡’이라는 철학적인 개념은 내가 감히 논하기 어려운 부분이고, 또 개개인마다 규정하는 선과 악의 개념과 이미지는 각기 다르겠지만, 일반적으로 여겨지는 착한 것. 착한 사람은 우리 사회가 말하는 강자와 성공의 이미지보다는 약자의 이미지와 중첩되는 부분이 더 많은 것이 사실이다.

언더 도그마. 약자(언더도그)가 강자(오버도그)보다 도덕적 우위에 있고, 강자는 비난받아 마땅하다고 여기는 믿음. 보통 언더도그마를 이야기 할 때는 주로 강자가 비난 받는 것에 대한 부당함을 많이 이야기 한다. 약자=善, 강자=惡 로 인식되는 이분법 속에서 어떤 사건이 생기면 惡에 속한 강자가 비난을 받는 경향성이 강하다는 것이다.

그러나 나는 그 전에 善이 强이 될 수 없는 것에 대해 의문을 품고 싶다. 어릴 때 우리는 부모님으로부터 ‘착한 어린이’가 되어야 한다고 배웠다. 어릴 때 읽던 동화 속 세상은 착한 사람이 이기는 곳이었다. 열심히 하면 된다고 믿었었고 옳은 일을 하면 칭찬을 받았으며 거짓말을 하면 혼이 났다. 그리고 그 착한 어린이는 나이가 들어감에 따라 열심히 한다고 다 되는 것이 아님을 깨닫고, 옳은 일을 하기에 앞서 ‘사회에서 통용되는 것’이라고 불리는 악습들과 온갖 통념과 부딪히며 점점, 어른이 된다.

어른이 된다는 아픔에서 우리가 듣는  것. ‘사회는 원래 그런거야.’

난 아직 온전히 사회를 알지 못한다.
짧게 나마 내가 느낀 사회는, 들어온 사회는 옳은 것에 대해 냉소를 보내는 곳이었다.
기업에서 일하는 개인은 사람이기 이전에 비용이고, 사회라는 피라미드에 올라간 사람은 털어서 먼지가 나오는 것이 당연하며, 실력보다 접대가 중요하고, 도전하는 사람은 무모한 사람이며, 선망받는 직업/직장에 속한 사람이라면, 혹은 돈이 많은 사람이라면 그의 인격과 상관 없이 우러러보는 곳. 젊은 이가 의문을 품으면,  ‘너가 아직 어려서 그래. 지나면 알거야. 껄껄껄’ 치기어린 생각으로 넘어가는 것.

나는 따뜻한 강자가 되고싶다. 아직 세상을 몰라 그럴거라고 누가 깎아내려도. 혹여 앞으로 살면서 어른이 되면서 이런 지금의 내 생각이 치기 어린 생각이었다 생각할 지라도. 난 부끄러운 사람이 되고싶지 않다.

내가 말하는 강자는 돈을 많이 버는 사람도, 남들이 우러러보는 권력을 쥔 사람이 아니다. 사람의 맘을 움직일 수 있는 사람. 옳은 뜻을 지키는 사람. 그리고 옳은 것이 맞다는 것을 결국 증명해 보일 수 있는 사람이다.

그런 옳은 뜻을 맞다고 떳떳하게 증명해보이는 그런 따뜻한 강자가 사회에서도 존경 받는 것이 당연한 세상이 오길 희망한다.