Study - Programming/C/C++2009. 4. 6. 19:28
  어제 _beginthreadex()함수를 호출하다가 이런일이 있었다. 예를 들면 대충 이러한 상황이였다.

class ex_Class  //예제 클래스
{
private:
  unsigned WINAPI ThreadProc(LPVOID lParam)  //스레드를 위한 함수
  {
    //코오드
  }
  void TestFunction();

}
  void ex_Class::TestFunction()
  {
    _beginthreadex(NULL,0,ThreadProc,...);//스레드 생성
  }


이러니 _beginthreadex부분에서 컴파일 에러가 났다.  이유는 ThreadProc가 올바르지 않는 호출이라고..
처음에는 왜 그런지 몰라서 한참 헤매다가 나중에 겨우 이유를 찾았다.(당시에 인터넷도 안되고 해서 로컬 MSDN으로 한참 고생했다.)


우선 ThreadProc는 &ex_Class:ThreadProc같은 형태로 인자를 넘겨야 한다. ex_Class의 멤버함수이므로 접근 한정자를 붙여 주고 포인터이므로 &를 붙여 준다.
다음으로ThreadProc는 static으로 설정해야 한다. 함수 포인터의 호출이기 때문에 어느 한 객체에 소속되지 않게 하기 위해서 static으로 선언해야 한다. 이때문에 함수 내에서 멤버의 접근을 하기 위해서는 다음과 같은 방식으로 접근하여야 한다.

static unsigned WINAPI ThreadProc(LPVOID lParam)
{
  ex_Class *cls = (ex_Class*)lParam;
  cls->(멤버) 접근;
}

이는 꼭 스레드호출만이 아니라 함수포인터와 관련된 부분에서 해야 하는 것이다. 이런 상황에서 이런 오류를 만나서 예시가 이렇게 되었을뿐, 다른 상황에서도 마찬가지이다.
으흠... 아직 배우고 공부해야 할게 많다.
Posted by 머리
Study - Programming/C/C++2008. 12. 15. 03:42


달팽이 모양 수열
한번 만들어 봤다.

오랫만에 하니까 영 하는게 어색하다. 아..잠자야 하는데..

Posted by 머리
Study- MSC/Computer2008. 10. 24. 19:48
  이번 포스팅에서는 동적할당을 객체의 생성쪽으로 확장해 보고자 한다. 먼저 말해두지만 이 포스팅은 포인터나 객체, 클래스를 설명하기 위한 포스팅이 아니다. 어디까지나 이런 사항에 대한 기본적인 지식은 알고 있다고 가정하고 진행하겠다. 우선 C++에서 Example이라는 클래스가 있고, 그것에 대한 객체를 생성해 보자.

Example ex;

  자. ex라는 객체가 생성되었다. 아마 특별한 문제 없이 제대로 돌아갈 것이다. 그리고 파괴도 잘 될 것이다. 하지만 이런 방식의 객체 생성은 권하고 싶지 않다. 대신 이런 객체의 생성을 권한다.

Example* pEx = new Example();

  위 방식은  Example라는 클래스 형식으로 메모리 공간에 할당을 한 후 그 주소를 pEx 포인터 변수에 넣어서 사용하게 하는 방식이다. 앞선 포스팅에서, 메모리의 어딘가에(HEAP) 공간을 할당한다고 했는데 위 방식도 바로 이런 방식이다. 이렇게 해 놓으면 이어서 이렇게도 가능하다

Example *pEx = new Example();
pEx = new Example();

  잘 이해가 가지 않을것이다. 무슨 이야기냐면 한 객체를 메모리에 생성하여 한 포인터에 주소를 기억시켰는데, 그 포인터를 재사용하여 또다른 객체를 또 생성하여 그 주소를 넣을 수 있다는 이야기이다. 물론 위 코드는 첫 객체의 해제에서 문제가 발생하지만 이런식으로 좀 더 코드에 유연성을 줄 수 있다. 그렇지 않으면 Example ex1,ex2; 등의 방식으로 객체를 생성해야 하는 문제가 발생한다.
  앞서 말한 유연성 외에도 이런 방식의 동적 할당을 통한 객체 생성은 맨 처음 말한 동적할당의 장점을 최대한 살릴 수가 있게 된다. 객체는 일반 변수보다 여기 저기서 사용될 가능성이 많다. 무슨 말이냐면 지역 변수 이상의 용도로 사용될 가능성이 많다는 이야기이다. 만약에 게임을 만들때 적을 표현하는 클래스가 있고 그 객체를 생성한다고 하면 상황에 따라 계속해서 적을 만들어 내야 하므로 동적 할당이 필요 할 수 밖에 없다.(int형으로 적을 표현할수는 없지 않은가?)
  이제까지는 객체를 동적할당 할 때 포인터를 이용하였다. 그 이유는 C++은 기본적으로 Call by Value 방식이기 때문이기 때문인데 이는 변수 및 객체의 사용을 한정적인 위치에서만 사용할 수 밖에 없게 만든다. 이 틀을 극복하기 위해서 메모리상의 주소로 읽기 위한 포인터가 사용되는데, 여기서 한단계 더 나가서 레퍼런스라는 개념이 나온다. 적어도 여기서는 Call by Reference와 Call by Address의 개념을 다르게 두자. Call by Address는 결론적으로는 포인터의 값을 이용한 Call by Value로 볼 수 있다. 엄밀하게 말하면 Call by Reference와는 다르다.(물론 내부적으로 이놈도 포인터를 쓰긴 쓴다.)
  말이 샜는데, C++ 이후의 객체 지향 언어는 기본 참조 방식을 Call by Value가 아니라 Call by Reference를 채택한 경우가 많다. JAVA가 그렇고, C#이 그러며, 심지어 Visual Basic도 Call by Reference가 기본이다.
  무슨 말이냐면 만약에

Example ex;

라는 코드가 있으면 C++에서는 ex가 객체 그 자체이지만 JAVA나 C#등에서는 저것은 그냥 참조를 위한 레퍼런스에 불과하지 객체 자체는 아니다. 즉 아무것도 못한다. 레퍼런스는 포인터처럼 메모리 상의 어떤 것을 가리켜야 그 의미가 있다. 즉

Example ex = new Example();

  와 같이 객체를 생성하고 그것을 참조하여야 한다.
  말이 많았다. 정작 하고 싶은 말은 '동적할당은 메모리 어딘가에 공간을 할당하고 포인터를 이용하여 그것을 참조한다, 그리고 이는 객체에서도 마찬가지이며 좀더 나아가 레퍼런스는 참조 없이는 아무런 의미가 없다'였는데 이것을 표현하기 위해 쓸데없는 말이 너무 많았던 것 같다.
  아무쪼록 이 글을 읽고 뭔가 '아!'하고 깨달음(?)을 얻는 프로그래머 지망생이 있으면 좋겠다. 그렇게 기원하면서 이상 3회에 걸친 포스팅을 마치고자 한다.
Posted by 머리
Study - Programming/C/C++2008. 10. 21. 19:37
  요즘 '조엘 온 소프트웨어'라는 책을 읽고 있는데 그 책에서 문자열 관련 이야기가 나오기에 그 내용을 참고하여 한번 이야기 하고자 한다.

  C의 문자열 구조는 먼저 문자열 내용이 있고 그 다음 '널 문자'가 들어가는 형식이다. 즉 "Hello"라는 문자열을 표현하려면 

'H' 'e' 'l' 'l'o' '\0' (단,\0 은 Null Characher)

  이렇게 6글자(sizeof(char) == 1이므로 6Byte)를 차지하게 된다. 이 Null Character의 사용 용도는 문자열의 끝(End of String)을 나타내기 위한 방법인데, 적어도 C에서는 이 문자가 없다면 메모리 어느 부분에 우연히 이 문자가 있는 것을 발견할때까지 계속해서 읽게 되어 엉뚱한 문자열이 나오게 된다.

  언뜻 보면 무슨 내용이 들어 있을 지 모르는 메모리에 이런 방식으로 문자열을 담는 것은 꽤 괜찮은 방법처럼 보인다. 하지만 조금 만 더 생각해보면 이것보다 좋은 대안을 찾을 수 있다.
  무엇보다 위 방식의 가장 큰 단점은 무슨 작업을 하려면 반드시 문자열 처음부터 끝까지 탐색을 하러 가야 한다는 것이다.
  예를 들어보자. 문자열의 길이를 알아내는 함수(strlen)를 구현해 보자고 한다면 문자열의 첫 포인터에서 Null Character을 찾을 때까지 포인터를 이동시켜야 한다.
  그런데 만약에 이 문자열의 길이가 100이라면? 그리고 1000이라면? 이런식으로 가면 문자열이 길면 길수록 그 처리 속도는 길어질 것이다. 다른 예로, 두 문자열을 잇는 함수(strcat)를 구현하자고 하면 두 문자열의 길이를 알아서 한 문자열에 할당된 크기를 다시 합친 크기로 재할당 해야 하고 문자열의 끝으로 이동해서 복사하는 과정을 수행해야 한다. 이것 역시 문자열의 길이를 구하는 과정에서부터 속도의 문제가 발생한다.
  이런 것을 해결하기 위한 방법으로는 뭐가 있을까? 이런 방법이 있을 수 있다.

'5' 'H' 'e' 'l' 'l' 'o'

  즉, 문자열의 첫 바이트에 문자열의 길이를 넣는 것이다. 이러면 굳이 끝까지 가서 널 문자를 찾을 필요 없이 길이를 첫 바이트에서 알 수 있으므로 그 크기 만큼 포인터를 이동해서 해결 할 수 있다. 여기서 주의해야 할 점은 끝부분에 Null Character을 넣는 방식은 하지 말라는 것이다. 그렇게 하면 정말 이도 저도 아닌 형편없는 문자열 표현 방식이 된다.
  다른 방법으로는 String Class를 구현하는 것인데, 이미 객체지향 프로그래밍 언어나 좀더 고급언어인 경우에는 지원되는 경우가 많다. 클래스의 멤버로 다음과 같은 예를 들 수 있다.

1. 문자열의 저장할 변수
2. 문자열의 길이를 저장할 변수
3. 기타 문자열 관련 함수

  위 방법으로는 효과적이고 자기 나름대로의 알고리즘으로 효율적으로 문자열을 관리 할 수 있을 것이다. 그리고 나 같으면 문자열을 저장 할 때 더이상 Null Character은 넣지 않도록 구현 할 것이다. 그리고 C++같은 경우라면 Operator Overloading등의 기능을 통해서 출력 및 입력, 기타 연산등의 방법도 구현해 보겠다.다만 위의 방법은 각자의 클래스 구현으로 표준이 규정되어 있지 않다면 호환성에서 문제가 발생 할 수 있겠고 조금 무거울 것이다.

  이외에도 많은 방법이 있을 것이다. 중요한 것은 이런 기본 데이터 타입에 만족하지 않고, 뭔가 다른 방식을 조금씩 연구하고 구현해 본다면 많은 도움이 될 것이다.
Posted by 머리
Study - Programming/C/C++2007. 12. 8. 23:11
사용자 삽입 이미지

사용자 삽입 이미지


2007년 2학기 C 프로그래밍 텀 프로젝트인 러시안 테트리스이다.

참 고생 많이 했다.. 잘 알지도 못하는 MFC가지고 지지고 볶는다고.. 보면 Ver1과 모습이 좀 다르다. 블럭을 비트맵 처리하였고, 크기도 조금 줄였다.

하지만 Game클래스는 거의 변화하지 않아 만드는데 그렇게 힘들이지는 않았다. 실제로 이 버전은 하루만에 환성 할 수 있었다.

하지만 문제는 인공지능.. 진짜 머리 나쁘다. 이거 랜덤이랑 붙어도 질것 같다. 동생이랑 해서 6연패.. 심히 걱정된다. 일단 이정도로 해놓고 시험 공부좀 하고 인공지능을 업그레이드 시켜 보아야 겠다.

Posted by 머리
Study - Programming/C/C++2007. 11. 17. 02:28
사용자 삽입 이미지


2007학년도 2학기 C프로그래밍 과목의 텀 프로젝트 과제이다.

러시안 테트리르라고 불리는 게임인데(참고로 이렇게 해서 검색 해보면 한개도 안나온다.)

판에 테트리스 블록을 하나씩 놓으면서 상대방이 못놓게 하는게 이 게임의 목적. 즉 내가 마지막으로 블록을 놓으면 이기는 게임이다.

MFC를 이용하였다. 내 첫 MFC 프로그램인데, 생각보다 순조롭게 일이 진행되어서 다행이다. 현재까지는 버그가 없어보인다.

자 여기서 추가해야 할 것은 컴퓨터의 인공지능. 원래 목적은 여기서 컴퓨터가 놓을 수 있게 만들고, 학생들이 자신들이 만든 컴퓨터 인공지능을 붙여서 경쟁하는 것이 목적이다.

지금은 게임 룰만 되도록 하였다. 즉 인공지능은 없다. 이제 남은 기간동안 만들어야 할 것이다.

소스코드는 아직 텀 프로젝트 기간이므로 올리지 않고 실행 파일만 올린다.
Posted by 머리
나의 이야기/Note2007. 11. 10. 01:01
  지금 내가 공부 하고 있는 언어들을 한번 세어 보면

1. C
2. C++
3. JAVA
4. C#
5. VB.NET
6. Delphi

  여기에 세부 분야까지 넣어 보면
1. API
2. MFC
3. TCP/IP

  뭐 이정도. 문제는 이런 것들을 그냥 배워 보고 싶다는 생각에 건드려만 본다는 것이다. C/C++이야 항상 만지고 있는 거니 예외라 치고, 델파이는 거의 안하니 제외 해도 너무 하려고 하는게 많다. 특히 C#이랑 JAVA는 의욕에 비해 하는게 너무 없는듯하다.

  지금 생각은 이렇다. 한 두가지 정도만 집중할것이냐 조금만 더 힘낼 것이냐. 솔직히 말해서 조금 버겁긴 하지만 그렇다고 못하겠는건 아니다. 그냥 진도가 너무 안나가는 것에 대한 불안감?

  그래도 대학 와서 내가 이쪽 분야 그동안 공부했던것과 비교해 본다면 결코 무리라는 생각은 안든다. 다만 걱정되는건 어린 시절 근 10년간 VB를 파 오면서 너무 공부하기에는 어렸었다는 것도 있었겠지만 여러가지를 많이 해보고 싶어서 이것 저것 해보다가 어중간하게 얕고 넓게(?) 익히게 되어서 그게 반복되지 않을까 신경쓰인다.

  1월 안에는 윈어플 큰거 하나 짜놓고 가긴 가야 하는데.. 제일 승산 있는게 무엇일까? 제일 승산있는건 MFC나 C#쪽인데.. 아무래도 최근에 새로 배우는 언어는 C#이 제일 무난하게 나가고 있어 조금만 더 하면 윈폼 시작할것이니. 아니면 지금 텀 프로젝트한다고 공부중인 MFC도 요즘들어 뭔가 감이 잡혀가기 시작해서 조금만 더 노력하면 속도가 붙을 것 같은데..

  이렇게 해봐야 겠다. JAVA로는 뭐 만드는건 잠시 미루되 꾸준히 공부는 하고 MFC는 텀에 충실하되 실력이 늘 수 있게, 그리고 C#으로는 뭘 만들도록 주로 공부해 봐야지. 이렇게 실천할수 있으면 얼마나 좋아.
Posted by 머리
Study - Programming/C/C++2007. 11. 6. 02:12

  Int Class에 이어 이번에 만들어 본 것은 String Class. C/C++에서의 문자열 처리를 보완하기 위하여 만들어 본 클래스이다. VB나 기타 다른 언어의 String형과 비슷하게 만들어 보았다.
구현한 것은 다음과 같다.

1. Constructors/Destructor
2. Adding Operator(+)
3. Equal Operator(==)
3. Assignment Operator(=)
4. Lenght Method
5. Standard IO Interface
  이렇게 나열하고 보니 몇가지 구현해보고 싶은게 많이 생기네.. Mid,Left,Right Method나 != Operator 같은것들.. 뭐 다음 기회로 미루자.

int Class 만들때보다 연산자 오버로딩을 좀 더 익숙하게 다룬 것 같다. 다음에 만들어 볼 것은 Matrix Class.

invalid-file

Class_String

Posted by 머리
Study - Programming/C/C++2007. 11. 4. 01:44

  솔직히 말해서 C++은 공부를 거의 문법 스펙을 읽기만 하고 실제로 짜본건 거의 없었다. 한떄는 C보다 C++을 훨씬 많이 하곤 했었는데 지금은 거의 C로만하니 당연히 까먹을 수밖에.

  거기다 이번에 하드디스크 데이터를 날려먹으면서 그동안 연습해왔던 C++코드까지 다 잃어버려서 새로 시작하자는 의미로 하나 하나 클래스 몇개를 만들어 보기로 했다.

  그 첫번째로 우선 Integer Class를 구현해 보았다. 기본 데이터 타입인 int를 직접 만들어 본 것. 역시 많이 버벅대었다. 제대로 되었는지도 잘 모르겠고. 특히 멤버의 생성과 소멸 부분에서 많이 헤매었고 연산자 오버로딩 부분도 아직 잘 모르겠다.

  구현한 것들은 다음과 같다.
1. Constructor//Destructor
2. Assignment Operator
3. Relationship Operator
4. Arithmetic Operator
5. Array Operator

  뭐 대부분이 연산자와 관련된 부분이지만 실제 필요한 부분은 거의 넣은 것 같다. 많이 부족하지만 앞으로 많이 공부해 봐야지.

  다음 구현할 것은 String Class. 힘내자.

invalid-file

Integer_class

Posted by 머리
Study - Programming/C/C++2007. 9. 2. 23:16

#include <iostream>
using namespace std;
class Example
{
public:
       Example()
       {
                x = 3;
       }
       friend void Show(Example &ex);
private:
       int x;
                  
};

void Show(Example &e)
{
     cout << "x is : " << e.x << endl;
}

int main(void)
{
    Example ex;
   
    Show(ex);

    return 0;
   
}
 
  우선 Show라는 함수의 정의 부분을 보자. 일반 멤버 함수의 정의와는 달리 Example라는 클래스에 있음에도 Example :: 이런 식으로 스코프(Scope)를 해 주지 않았다. 그럼 위로 올라가 Example클래스의 Show함수의 선언을 보자. 특이한 키워드가 붙어 있을 것이다. friend 이 키워들를 붙이면 Show라는 함수는 이 클래스의 멤버 함수가 아니게 된다. 굳이 구분하자면 전역 함수쯤 될 것이다.
 main함수 안에서 Show의 사용을 보자. ex.Show()가 아닌 그냥 Show()로 불러 들였다. 그리고 인자를 보면 ex라는 객체를 레퍼런스로 넣었다. 외부 함수라는 것이다. 그런데 실행을 해 보면 신기하게 ex라는 객체에 private로 선언되어 있는 멤버 변수 x의 값을 불러 온것을 알 수 있다. 즉 friend 함수는 예외적으로 클래스 내부의 멤버에 접근 할 수 있게 해 주는 역할을 한다.

Posted by 머리