* Qt 5.2.1 내려받기  (아래의 예는 Visual Studio 2010 용을 받아서 설치한 경우이다. Qt Creator 3.0.1 은 자동으로 함께 설치된다,)

 

Qt Creator 를 시작한 후 메뉴에서

         File --> New File or Project...

를 택한다. 그리고 New 창에서 다음 그림에서와 같이

        Applications --> Qt Quick Application

을 택하고 "Choose..." 버튼을 클릭한다.

 

이어 나타나는 New Qt qUICK aPPLICATION 창에서 애플리케이션이 생성될 폴더와 이름을 정한다. 원하는 폴더거 없는 경우 그 우측의 "Browse" 버튼을 클릭하여 생성하거나 선택한다.

 

다음 창에서는 Qt Quick Componenet Set 을 정한다. Qt 5.0 이상은 "Qt Quick 2.0" 으ㅜㄹ 택한다.

 

다음 창에서는 Kit Selection 을 설정한다. (이 예에서는 Visual C 2010 용으로 설치한 경우이다.)

 

다음 창에서는 Project Management 를 확인한다. 앞으로 main.qml 파일만 수정하고 저장한 후 실행하면 된다. (실행 버튼만 누르면 빌드는 저절로 된다.)

 

 

* main.cpp 의 내용 (자동으로 생성된 후 수정되지 않음)

 

#include <QtGui/QGuiApplication>

#include "qtquick2applicationviewer.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/ThirdHelloQtQuickApp/main.qml"));
    viewer.showExpanded();

    return app.exec();
}
 

 

* main.qml 의 내용 (자동 생성된 main.qml 파일의 내용을 아래 처럼 수정한다.)

import QtQuick 2.0

Rectangle {
    id: page
    width: 320; height: 160
    color: "lightgray"

    Text {
        id: helloText
        text: "Hello, world!<br /><br />안녕하세요?"
        y: 25
        anchors.horizontalCenter: page.horizontalCenter
        font.pointSize: 24; font.bold: true; font.italic: true
    }
}

 

 

* Releae/Debug 변경하기 그리고 실행하기 (Qt Creator 창의 좌측 아래 부분)

 

 

* Release 배포를 위해 PATH 에 지정된 폴더에 꼭 있어야 하는 파일들:

icudt51.dll
icuin51.dll
icuuc51.dll
libEGL.dll
libGLESv2.dll
Qt5Core.dll
Qt5Gui.dll
Qt5Network.dll
Qt5Qml.dll
Qt5Quick.dll
ThirdHelloQtQuickApp.exe
 
 

 

* 만일 PATH 로 지정된 경로에 libEGL.dll 이 없으면 다음 에러 메시지 창이 뜬다.

 

 

 

* 실행 결과:

 

 

 

 

 

Posted by Scripter
,

SymbolicC++  는 GiNaC 처럼 심볼 처리 수학식 계산을 지원하지만, 리눅스 계열 뿐만 아니라 윈도우 환경에서도 Visual C++ 나 MinGW 의 g++ 와 함께 사용할 수 있는 수학 심볼 처리 라이브러리이다.

 

* SymbolicC++  내려받기

* Wikipedia 에서 설명하는 SymbolicC++

 

* MinGW 의 g++ 를 위한 SymbolicC++  라이브러리 만들기

모든 작업은 MinGW\msys\1.0 폴더에 있는 msys.bat 파일을 실행하여 msys 창에서 한다.

$ ./configure

$ make

$ make install

$ make clean

생성된 라이브러리 파일 libsymbolicc++.a 와 libsymbolicc++.la 는 /usr/local/lib 폴더에 존재하고, 헤더 파일 symbolicc++.h 는 /usr/local/include 폴더에 존재한다.

 

* 간단한 인터프리터 소스

/*
    SymbolicC++ : An object oriented computer algebra system written in C++

    Copyright (C) 2008 Yorick Hardy and Willi-Hans Steeb

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


// interpreter.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>
#include <cmath>
#include "symbolicc++.h"
using namespace std;

double error(string s)
{ cerr << "Error: " << s << ", using 0." << endl; return 0.0; }

class token
{
  private:
   int is_value;
   Symbolic v;
   string t;
   static map<string,Symbolic> values;
  public:
   token() : is_value(0), v(0), t("") {};
   token(const Symbolic &s) : is_value(1), v(s), t("") {};
   token(const string &s) : is_value(0), v(0), t(s)  {};
   Symbolic value();
   string name() { return t; }
   int isvalue() { return is_value; }
   Symbolic set(const Symbolic &d) { return values[t]=d; }
   int operator==(string s) { return (!is_value) && (t == s); }
   friend ostream& operator << (ostream&,token);
};

map<string,Symbolic> token::values;

Symbolic token::value()
{
  if(is_value) return v;
  char *end;
  int vali=(int)strtol(t.c_str(),&end,10);
  if(*end == '\0') return Symbolic(vali);
  double vald=strtod(t.c_str(),&end);
  if(*end == '\0') return Symbolic(vald);
  if(values.count(t)>0) return values[t];
  return Symbolic(t);
}

ostream& operator << (ostream& o,token t)
{ if(t.is_value) o << t.v; else o << t.t; return o;}

vector<token>
get_tokens(string s,string separator[],string ignore[])
{
  int i = 0, j, istoken = 0;
  vector<token> v;
  string value = "";
  while(i<(int)s.length())
  {
   istoken = 0;
   for(j=0;ignore[j] != "" && i<(int)s.length();j++)
    if(s.substr(i,ignore[j].length()) == ignore[j])
     i += ignore[j].length(), j = -1, istoken = 1;
   for(j=0;separator[j] != "" && !istoken;j++)
    if(s.substr(i,separator[j].length()) == separator[j])
    {
     if(value != "") { v.push_back(token(value)); value = ""; }
     v.push_back(token(separator[j]));
     i += separator[j].length();
     istoken = 1;
    }
   if(!istoken) value += s[i++];
   else if(value!="") { v.push_back(token(value)); value = ""; }
  }
  if(value != "") v.push_back(token(value));
  return v;
}

Symbolic spow(const Symbolic &x,const Symbolic &y) { return (x^y); }
Symbolic smul(const Symbolic &x,const Symbolic &y) { return x*y;   }
Symbolic sdiv(const Symbolic &x,const Symbolic &y) { return x/y;   }
Symbolic sadd(const Symbolic &x,const Symbolic &y) { return x+y;   }
Symbolic ssub(const Symbolic &x,const Symbolic &y) { return x-y;   }

Symbolic ssqrt(const vector<Symbolic> &x)  { return sqrt(x[0]);           }
Symbolic scos(const vector<Symbolic> &x)   { return cos(x[0]);            }
Symbolic ssin(const vector<Symbolic> &x)   { return sin(x[0]);            }
Symbolic stan(const vector<Symbolic> &x)   { return tan(x[0]);            }
Symbolic sexp(const vector<Symbolic> &x)   { return exp(x[0]);            }
Symbolic sln(const vector<Symbolic> &x)    { return ln(x[0]);             }
Symbolic slog(const vector<Symbolic> &x)   { return log(x[0],x[1]);       }
Symbolic sdf(const vector<Symbolic> &x)    { return df(x[0],x[1]);        }
Symbolic ssubst(const vector<Symbolic> &x) { return x[0].subst(x[1],x[2]);}
Symbolic sfunc(const vector<Symbolic> &x)  { return x[0][x[1]];           }

Symbolic evaluate(token t);

struct function {
 string name;
 int    args;
 Symbolic (*impl)(const vector<Symbolic>&);
};

Symbolic evaluate_tokens(vector<token> v)
{
  vector<token> v2, v3;
  int parenthesis, i, j, k;
  // function names, arity, and their implementation
  function functions[] = {
   { "sqrt",     1, ssqrt  },
   { "cos",      1, scos   },
   { "sin",      1, ssin   },
   { "tan",      1, stan   },
   { "exp",      1, sexp   },
   { "ln",       1, sln    },
   { "log",      2, slog   },
   { "df",       2, sdf    },
   { "subst",    3, ssubst },
   { "function", 2, sfunc  },
   { "" } };

  // default left operands for binary operators
  double initleft[] = { 1.0, 1.0, 0.0 };
  // binary operators and their implementation
  string opnames[][4] = { { "^", "" }, { "*", "/", "" }, { "+", "-", "" } };
  Symbolic (*opimpl[][3])(const Symbolic&,const Symbolic&) =
     { { spow }, { smul, sdiv }, { sadd, ssub } };

  // check for the assignment statement
  if(v.size()>2 && v[1] == "=") {
    for(j=2;j<(int)v.size();j++) v2.push_back(v[j]);
    return v[0].set(evaluate_tokens(v2));
  }

  // evaluate parenthesis first
  for(j=0;j<(int)v.size();j++)
  {
   if(v[j] == ")") return error("unbalanced parenthesis");
   else if(v[j] == "(")
   {
    for(parenthesis=1,j++;parenthesis && j<(int)v.size();j++)
    {
     if(v[j] == "(") parenthesis++;
     if(v[j] == ")") parenthesis--;
     // artificially end the parenthesized expression
     if(v[j] == "," && parenthesis == 1)
     {
      v2.push_back(token(evaluate_tokens(v3)));
      v3.clear();
     }
     else if(parenthesis) v3.push_back(v[j]);
    }
    if(parenthesis) return error("unbalanced parenthesis");
    v2.push_back(token(evaluate_tokens(v3)));
    v3.clear(); j--;
   }
   else v2.push_back(v[j]);
  }

  // evaluate functions
  for(j=0,v.clear();j<(int)v2.size();j++)
  {
   for(i=0;functions[i].name!="";i++)
   if(v2[j] == functions[i].name)
   {
    if(j+functions[i].args<(int)v2.size())
    {
      vector<Symbolic> args;
      for(k=1;k<=functions[i].args;k++)
       args.push_back(evaluate(v2[j+k]));
      v.push_back(token(functions[i].impl(args)));
      j+=functions[i].args;
    }
    else return error(functions[i].name           +
                      " without "                 +
                      char('0'+functions[i].args) +
                      " arguments");
    break;
   }
   if(functions[i].name=="") v.push_back(v2[j]);
  }
  // evaluate operators in order of precedence
  for(k=0,v2.clear();k<3;k++,v = v2,v2.clear())
  {
   token left(initleft[k]);
   for(j=0;j<(int)v.size();j++)
   {
    for(i=0;opnames[k][i]!="";i++)
    if(v[j] == opnames[k][i])
    {
     if(v2.size()) v2.pop_back();
     if(j+1<(int)v.size())
      v2.push_back(token(opimpl[k][i](evaluate(left),
                                      evaluate(v[++j]))));
     else return error(opnames[k][i]+" without second argument");
     break;
    }
    if(opnames[k][i]=="") v2.push_back(v[j]);
    left = v2.back();
   }
  }
  // check that evaluation gave a single result
  if(v.size() != 1)
  {
   for(j=0;j<(int)v.size();j++)
    cerr << "token " << j+1 << " : " << v[j] << endl;
   return error("could not evaluate expression");
  }
  return v[0].value();
}

Symbolic evaluate(token t)
{ vector<token> v; v.push_back(t); return evaluate_tokens(v); }

Symbolic evaluateformula(istream &s)
{
  char c;
  string expression;
  static string ws[] = { " ", "\t", "\n", "\r", "" };
  static string separator[] = { "=", "+", "-", "*", "/",
                                "^", "(", ")", ",", "" };
  do if((c = s.get()) != ';' && !s.eof()) expression += c;
  while(c != ';' && !s.eof());
  if(c != ';') return error("formula not terminated");
  vector<token> v = get_tokens(expression,separator,ws);
  return evaluate_tokens(v);
}

int main(void)
{
  while(!cin.eof())
  cout << " -> " << evaluateformula(cin) << endl;
  return 0;
}

 

* 컴파일 및 실행 (인터프리터를 실행하면 세미콜론(;)으로 끝나는 구문을 계산해준다.)

$ g++ -o interpreter interpreter.cpp -lsymbolicc++

$ ./interpreter
(x - 1)^3;
 -> x^(3)-3*x^(2)+3*x-1
2^3 - 2*3 + 5;
 -> 7
(x^2 - x + 1)*(x^2 + x + 1) ;
 -> x^(4)+x^(2)+1
2^10;
 -> 1024


 

Posted by Scripter
,

SymbolicC++  는 GiNaC 처럼 심볼 처리 수학식 계산을 지원하지만, 리눅스 계열 뿐만 아니라 윈도우 환경에서도 Visual C++ 나 MinGW 의 g++ 와 함께 사용할 수 있는 수학 심볼 처리 라이브러리이다.

 

* SymbolicC++  내려받기

* Wikipedia 에서 설명하는 SymbolicC++

 

* Visual C++ 를 위한 SymbolicC++  라이브러리 만들기

Visual Studio 에서 솔루션 파일 SymbolicC++3.sin 을 열고 아래 그림 처럼 메뉴 탭에서 Dynamic 이라고 설정된 곳을 Static 으로 변경하고 빌드한다.

그러면 에러와 경고가 몇 개 쏟아질 것이다.

 

* 에러 해결하기

SymbolicC++ 를 빌드하는 과정에서 C:\Program Files (x86)\Microsoft Visual Studio 10\VC\include 폴더에 있는 파일 xlocmon 410 째 줄에서 에러가 걸린다. 이 줄을

                 _Str2 += '-', ++_Off;   ------>    _Str2 += '-'; ++_Off;

처럼 수정(즉 콤마를 세미콜론으로 수정)하여 다시 저장한다.

그러면 에러는 해결되고 경고(warning) 몇 개가 남는다.

 

* 몇 가지 경고(warning) 해결하기

1) SymbolicC++ 의 소스 파일 중에 integrate.cpp 파일에서 "변수 se 가 선언되었지만 사용되지 않았다"는 경고가 몇 곳 나온다.  이런 경고를 해결하려면, integrate.cpp 파일에서

        } catch(const SymbolicError &se) {}

처럼 된 중을 모두 찾아

        } catch(const SymbolicError &se) { std::cout << se.message() << std::endl; }

처럼 수정하고, 이 파일의 선두 부분에 include 문

        #include <iostream>

을 추가한다..

 

2) equation.cpp 파일의 95 째 줄

        { return lhs.compare(rhs); }


        { return (lhs.compare(rhs) == 0) ? false : true; }

로 수정한다.

 

3) sum.cpp 파일의 373 째 줄

        if(j != matchpart.end()); matchpart.erase(j);


         (j != matchpart.end()) matchpart.erase(j);

로 수정한다. (세미콜론 하나 제거)

 

* SymbolicC++ 를 이용하는 간단한 부정적분 예제

/*
    SymbolicC++ : An object oriented computer algebra system written in C++

    Copyright (C) 2008 Yorick Hardy and Willi-Hans Steeb

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


// integration.cpp

#include <iostream>
#include "symbolicc++.h"
using namespace std;

int main(void)
{
  Symbolic x("x"), c("c"), z("z"), y;

  z = z[x];
  y = (1-x)*(1-x)+cos(x)+x*exp(x)+c+z;

  cout << "y = " << y << endl;

  for(int i=0;i<3;i++)
  {
   y = integrate(y,x);
   y = y[integrate(x*exp(x),x) == x*exp(x) - exp(x)];
   cout << "y = " << y << endl;
  }

  return 0;
}

 

 

* 위의 예제 소스 컴파일하기 (컴파일 옵션 /MD 가 중요)

프롬프트> cl /EHsc /I SymbolicC++3-3.35-vc\include integration.cpp SymbolicC++3.lib /MD

 

* 실행하기

프롬프트> integration
y = x^(2)-2*x+cos(x)+x*e^x+c+z[x]+1
y = 1/3*x^(3)-x^(2)+sin(x)+x*e^x-e^x+c*x+int(z[x],x)+x
y = 1/12*x^(4)-1/3*x^(3)-cos(x)+x*e^x-2*e^x+1/2*c*x^(2)+int(z[x],x,x)+1/2*x^(2)
y = 1/60*x^(5)-1/12*x^(4)-sin(x)+x*e^x-3*e^x+1/6*c*x^(3)+int(z[x],x,x,x)+1/6*x^(3)

 

 

Posted by Scripter
,

C/C++ 언어 프로그래밍에서 까다로운 부분 중의 하나는 획득했던(할당받았던) 메모리를 여하히 해제하느냐이다. 프로그램밍의 사소한 오류로 메모리 부족 현상이 쉽게 일어나기 때문이다.

프로그램밍의 사소한 오류로 메모리 부족 현상이 쉽게 일어나기 때문이다.

자바 언어, 파이썬 언어, C# 언어 등은 자동으로 쓰레기 수집(garbage collection)이 이루어지므로 거의 신경쓰지 않아도 되지만, C 언어는 소스 작성하는 프로그래머가 직접해야 한다.

오래 전(10여년 전)에 Hans Boehm 가 만들었던 C/C++ 언어용 쓰레기 수집기(Boehm-Demers-Weiser conservative garbage collector, 줄여사 BoehmGC 러고 부름)를 이용하여 컴파일되고 실행되는 소스이다. 이 쓰레기 수집기를 쓰면, 메모리 해제(free)를 프로그래머가 신경쓰지 않아도 된다. 그렇게 하기 위해서는 헤더 파일 추가 구문

                    #include "gc.h"     또는      #include "gc/gc.h"
        또는      #include "gc_cpp.h"     또는      #include "gc/gc_cpp.h"

가 있어야 하고,  함수 malloc(크기) 대신에 매크로 GC_MALLOC(크기) 를, 함수 realloc(포인터, 크기) 대신에 매크로 GC_REALLOC(포인터, 크기) 를 사용해야 한다. 좀 더 좋은 성능을 위해서는 GC_MALLOC_ATOMIC(크기) 과 GC_enable_incremental() 을 사용하기도 한다. GC_MALLOC_ATOMIC 은 포인터를 전혀 갖지 않은 객체에 대하여만 적용된다. 


MinGW 의 gcc 나 Visual C++ 2010 용으로 동작하는지는 아직 확인 되지는 않았으나, Cygwin에는 Hans Boehm 의 쓰레기 수집기가 이미 설치되어 있어서, Cygwin 의  g++ 4.5.3 으로 컴파일할 수 있었다.

아래의 두 소스는 워낙 오래된 것이라서 #include 부분과 using namespace 부분을 수정 또는 추가하여 현재의 컴파일러로 컴파일되게 고쳤다.

* C++ 언어용 쓰레기 수집  벤치마크 테스트 (파일명: GCBench_OGC.cpp)

// This is adapted from a benchmark written by John Ellis and Pete Kovac
// of Post Communications.
// It was modified by Hans Boehm of Silicon Graphics.
// Translated to C++ 30 May 1997 by William D Clinger of Northeastern Univ.
//
//      This is no substitute for real applications.  No actual application
//      is likely to behave in exactly this way.  However, this benchmark was
//      designed to be more representative of real applications than other
//      Java GC benchmarks of which we are aware.
//      It attempts to model those properties of allocation requests that
//      are important to current GC techniques.
//      It is designed to be used either to obtain a single overall performance
//      number, or to give a more detailed estimate of how collector
//      performance varies with object lifetimes.  It prints the time
//      required to allocate and collect balanced binary trees of various
//      sizes.  Smaller trees result in shorter object lifetimes.  Each cycle
//      allocates roughly the same amount of memory.
//      Two data structures are kept around during the entire process, so
//      that the measured performance is representative of applications
//      that maintain some live in-memory data.  One of these is a tree
//      containing many pointers.  The other is a large array containing
//      double precision floating point numbers.  Both should be of comparable
//      size.
//
//      The results are only really meaningful together with a specification
//      of how much memory was used.  It is possible to trade memory for
//      better time performance.  This benchmark should be run in a 32 MB
//      heap, though we don't currently know how to enforce that uniformly.
//
//      Unlike the original Ellis and Kovac benchmark, we do not attempt
//      measure pause times.  This facility should eventually be added back
//      in.  There are several reasons for omitting it for now.  The original
//      implementation depended on assumptions about the thread scheduler
//      that don't hold uniformly.  The results really measure both the
//      scheduler and GC.  Pause time measurements tend to not fit well with
//      current benchmark suites.  As far as we know, none of the current
//      commercial Java implementations seriously attempt to minimize GC pause
//      times.

#include <new>          // #include <new.h>
#include <iostream>     // #include <iostream.h>
#include <sys/time.h>

#ifdef GC
#  include "gc.h"
#endif

using namespace std;

//  These macros were a quick hack for the Macintosh.
//
//  #define currentTime() clock()
//  #define elapsedTime(x) ((1000*(x))/CLOCKS_PER_SEC)

#define currentTime() stats_rtclock()
#define elapsedTime(x) (x)

/* Get the current time in milliseconds */

unsigned
stats_rtclock( void )
{
  struct timeval t;
  struct timezone tz;

  if (gettimeofday( &t, &tz ) == -1)
    return 0;
  return (t.tv_sec * 1000 + t.tv_usec / 1000);
}

static const int kStretchTreeDepth    = 18;      // about 16Mb
static const int kLongLivedTreeDepth  = 16;  // about 4Mb
static const int kArraySize  = 500000;  // about 4Mb
static const int kMinTreeDepth = 4;
static const int kMaxTreeDepth = 16;

typedef struct Node0 *Node;

struct Node0 {
        Node left;
        Node right;
        int i, j;
        Node0(Node l, Node r) { left = l; right = r; }
        Node0() { left = 0; right = 0; }
#       ifndef GC
          ~Node0() { if (left) delete left; if (right) delete right; }
# endif
};

struct GCBench {

        // Nodes used by a tree of a given size
        static int TreeSize(int i) {
                return ((1 << (i + 1)) - 1);
        }

        // Number of iterations to use for a given tree depth
        static int NumIters(int i) {
                return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
        }

        // Build tree top down, assigning to older objects.
        static void Populate(int iDepth, Node thisNode) {
                if (iDepth<=0) {
                        return;
                } else {
                        iDepth--;
#   ifndef GC
                          thisNode->left  = new Node0();
                          thisNode->right = new Node0();
#   else
                          thisNode->left  = new (GC_NEW(Node0)) Node0();
                          thisNode->right = new (GC_NEW(Node0)) Node0();
#   endif
                        Populate (iDepth, thisNode->left);
                        Populate (iDepth, thisNode->right);
                }
        }

        // Build tree bottom-up
        static Node MakeTree(int iDepth) {
                if (iDepth<=0) {
#       ifndef GC
                        return new Node0();
#       else
                        return new (GC_NEW(Node0)) Node0();
#       endif
                } else {
#       ifndef GC
                        return new Node0(MakeTree(iDepth-1),
                                         MakeTree(iDepth-1));
#       else
                        return new (GC_NEW(Node0)) Node0(MakeTree(iDepth-1),
                                            MakeTree(iDepth-1));
#       endif
                }
        }

        static void PrintDiagnostics() {
#if 0
                long lFreeMemory = Runtime.getRuntime().freeMemory();
                long lTotalMemory = Runtime.getRuntime().totalMemory();

                System.out.print(" Total memory available="
                                 + lTotalMemory + " bytes");
                System.out.println("  Free memory=" + lFreeMemory + " bytes");
#endif
        }

        static void TimeConstruction(int depth) {
                long    tStart, tFinish;
                int     iNumIters = NumIters(depth);
                Node    tempTree;

                cout << "Creating " << iNumIters
                     << " trees of depth " << depth << endl;
               
                tStart = currentTime();
                for (int i = 0; i < iNumIters; ++i) {
#   ifndef GC
                          tempTree = new Node0();
#   else
                          tempTree = new (GC_NEW(Node0)) Node0();
#   endif
                        Populate(depth, tempTree);
#          ifndef GC
                          delete tempTree;
#   endif
                        tempTree = 0;
                }
                tFinish = currentTime();
                cout << "\tTop down construction took "
                     << elapsedTime(tFinish - tStart) << " msec" << endl;
                    
                tStart = currentTime();
                for (int i = 0; i < iNumIters; ++i) {
                        tempTree = MakeTree(depth);
#   ifndef GC
                          delete tempTree;
#   endif
                        tempTree = 0;
                }
                tFinish = currentTime();
                cout << "\tBottom up construction took "
                     << elapsedTime(tFinish - tStart) << " msec" << endl;

        }

        void main() {
                Node    root;
                Node    longLivedTree;
                Node    tempTree;
                long    tStart, tFinish;
                long    tElapsed;

#ifdef GC
// GC_full_freq = 30;
GC_enable_incremental();
#endif
                cout << "Garbage Collector Test" << endl;
                cout << " Live storage will peak at "
                     << 2 * sizeof(Node0) * TreeSize(kLongLivedTreeDepth) +
                        sizeof(double) * kArraySize
                     << " bytes." << endl << endl;
                cout << " Stretching memory with a binary tree of depth "
                     << kStretchTreeDepth << endl;
                PrintDiagnostics();
              
                tStart = currentTime();
               
                // Stretch the memory space quickly
                tempTree = MakeTree(kStretchTreeDepth);
#  ifndef GC
                  delete tempTree;
#  endif
                tempTree = 0;

                // Create a long lived object
                cout << " Creating a long-lived binary tree of depth "
                     << kLongLivedTreeDepth << endl;
#  ifndef GC
                  longLivedTree = new Node0();
#  else
                  longLivedTree = new (GC_NEW(Node0)) Node0();
#  endif
                Populate(kLongLivedTreeDepth, longLivedTree);

                // Create long-lived array, filling half of it
                cout << " Creating a long-lived array of "
                     << kArraySize << " doubles" << endl;
#  ifndef GC
                  double *array = new double[kArraySize];
#  else
                  double *array = (double *)
    GC_MALLOC_ATOMIC(sizeof(double) * kArraySize);
#  endif
                for (int i = 0; i < kArraySize/2; ++i) {
                        array[i] = 1.0/i;
                }
                PrintDiagnostics();

                for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2)
{
                        TimeConstruction(d);
                }

                if (longLivedTree == 0 || array[1000] != 1.0/1000)
                        cout << "Failed" << endl;
                                        // fake reference to LongLivedTree
                                        // and array
                                        // to keep them from being optimized away

                tFinish = currentTime();
                tElapsed = elapsedTime(tFinish-tStart);
                PrintDiagnostics();
                cout << "Completed in " << tElapsed << " msec" << endl;
#  ifdef GC
    cout << "Completed " << GC_gc_no << " collections" <<endl;
    cout << "Heap size is " << GC_get_heap_size() << endl;
#  endif
        }
};

main () {
    GCBench x;
    x.main();
}

 

* 쓰레기 수집기가 동작하지 않도록 컴파일하기
$ g++ -o GCBench GCBench.cpp -lgc

* 실행하기
$ ./GCBench
Garbage Collector Test
 Live storage will peak at 8194272 bytes.

 Stretching memory with a binary tree of depth 18
 Creating a long-lived binary tree of depth 16
 Creating a long-lived array of 500000 doubles
Creating 33824 trees of depth 4
        Top down construction took 351 msec
        Bottom up construction took 348 msec
Creating 8256 trees of depth 6
        Top down construction took 352 msec
        Bottom up construction took 350 msec
Creating 2052 trees of depth 8
        Top down construction took 350 msec
        Bottom up construction took 350 msec
Creating 512 trees of depth 10
        Top down construction took 358 msec
        Bottom up construction took 354 msec
Creating 128 trees of depth 12
        Top down construction took 357 msec
        Bottom up construction took 355 msec
Creating 32 trees of depth 14
        Top down construction took 355 msec
        Bottom up construction took 358 msec
Creating 8 trees of depth 16
        Top down construction took 371 msec
        Bottom up construction took 373 msec
Completed in 5239 msec

 

* 쓰레기 수집기가 동작하도록 컴파일하기
g++ -DGC -o GCBench GCBench.cpp -lgc

* 실행하기
$ ./GCBench
Garbage Collector Test
 Live storage will peak at 8194272 bytes.

 Stretching memory with a binary tree of depth 18
 Creating a long-lived binary tree of depth 16
 Creating a long-lived array of 500000 doubles
Creating 33824 trees of depth 4
        Top down construction took 132 msec
        Bottom up construction took 110 msec
Creating 8256 trees of depth 6
        Top down construction took 114 msec
        Bottom up construction took 109 msec
Creating 2052 trees of depth 8
        Top down construction took 115 msec
        Bottom up construction took 112 msec
Creating 512 trees of depth 10
        Top down construction took 116 msec
        Bottom up construction took 114 msec
Creating 128 trees of depth 12
        Top down construction took 122 msec
        Bottom up construction took 116 msec
Creating 32 trees of depth 14
        Top down construction took 122 msec
        Bottom up construction took 123 msec
Creating 8 trees of depth 16
        Top down construction took 137 msec
        Bottom up construction took 114 msec
Completed in 1759 msec
Completed 229 collections
Heap size is 27652096

 

* C++ 언어용 쓰레기 수집  벤치마크 테스트 (파일명: GCBench_OGC.cpp)

// This is adapted from a benchmark written by John Ellis and Pete Kovac
// of Post Communications.
// It was modified by Hans Boehm of Silicon Graphics.
// Translated to C++ 30 May 1997 by William D Clinger of Northeastern Univ.
//
//      This is no substitute for real applications.  No actual application
//      is likely to behave in exactly this way.  However, this benchmark was
//      designed to be more representative of real applications than other
//      Java GC benchmarks of which we are aware.
//      It attempts to model those properties of allocation requests that
//      are important to current GC techniques.
//      It is designed to be used either to obtain a single overall performance
//      number, or to give a more detailed estimate of how collector
//      performance varies with object lifetimes.  It prints the time
//      required to allocate and collect balanced binary trees of various
//      sizes.  Smaller trees result in shorter object lifetimes.  Each cycle
//      allocates roughly the same amount of memory.
//      Two data structures are kept around during the entire process, so
//      that the measured performance is representative of applications
//      that maintain some live in-memory data.  One of these is a tree
//      containing many pointers.  The other is a large array containing
//      double precision floating point numbers.  Both should be of comparable
//      size.
//
//      The results are only really meaningful together with a specification
//      of how much memory was used.  It is possible to trade memory for
//      better time performance.  This benchmark should be run in a 32 MB
//      heap, though we don't currently know how to enforce that uniformly.
//
//      Unlike the original Ellis and Kovac benchmark, we do not attempt
//      measure pause times.  This facility should eventually be added back
//      in.  There are several reasons for omitting it for now.  The original
//      implementation depended on assumptions about the thread scheduler
//      that don't hold uniformly.  The results really measure both the
//      scheduler and GC.  Pause time measurements tend to not fit well with
//      current benchmark suites.  As far as we know, none of the current
//      commercial Java implementations seriously attempt to minimize GC pause
//      times.

#include <new>         // #include <new.h>
#include <iostream>    // #include <iostream.h>
#include <sys/time.h>

#ifdef GC
#include "gc_cpp.h"    // #  include "gc.h"
#endif
#ifdef OGC
#  include "ogc.h"
#endif

using namespace std;

//  These macros were a quick hack for the Macintosh.
//
//  #define currentTime() clock()
//  #define elapsedTime(x) ((1000*(x))/CLOCKS_PER_SEC)

#define currentTime() stats_rtclock()
#define elapsedTime(x) (x)

/* Get the current time in milliseconds */

unsigned
stats_rtclock( void )
{
  struct timeval t;
  struct timezone tz;

  if (gettimeofday( &t, &tz ) == -1)
    return 0;
  return (t.tv_sec * 1000 + t.tv_usec / 1000);
}

static const int kStretchTreeDepth    = 18;      // about 16Mb
static const int kLongLivedTreeDepth  = 16;  // about 4Mb
static const int kArraySize  = 500000;  // about 4Mb
static const int kMinTreeDepth = 4;
static const int kMaxTreeDepth = 16;

struct Node0 {
#       ifdef OGC
          gc_ptr<Node0> left;
          gc_ptr<Node0> right;
          Node0(gc_ptr<Node0> l, gc_ptr<Node0> r) { left = l; right = r; }
# else
          Node0 * left;
          Node0 * right;
          Node0(Node0 *l, Node0 *r) { left = l; right = r; }
# endif
        int i, j;
        Node0() { left = 0; right = 0; }
#       if !defined(GC) && !defined(OGC)
          ~Node0() { if (left) delete left; if (right) delete right; }
# endif
};

#ifdef OGC
typedef gc_ptr<Node0> Node;
#else
typedef struct Node0 *Node;
#endif

struct GCBench {

        // Nodes used by a tree of a given size
        static int TreeSize(int i) {
                return ((1 << (i + 1)) - 1);
        }

        // Number of iterations to use for a given tree depth
        static int NumIters(int i) {
                return 2 * TreeSize(kStretchTreeDepth) / TreeSize(i);
        }

        // Build tree top down, assigning to older objects.
        static void Populate(int iDepth, Node thisNode) {
                if (iDepth<=0) {
                        return;
                } else {
                        iDepth--;
#   if defined(GC)
                          thisNode->left  = new (GC_NEW(Node0)) Node0();
                          thisNode->right = new (GC_NEW(Node0)) Node0();
#   elif defined(OGC)
                          thisNode->left  = gc_new Node0();
                          thisNode->right = gc_new Node0();
#   else
                          thisNode->left  = new Node0();
                          thisNode->right = new Node0();
#   endif
                        Populate (iDepth, thisNode->left);
                        Populate (iDepth, thisNode->right);
                }
        }

        // Build tree bottom-up
        static Node MakeTree(int iDepth) {
                if (iDepth<=0) {
#       if defined(GC)
                        return new (GC_NEW(Node0)) Node0();
#       elif defined(OGC)
                        return gc_new Node0();
#       else
                        return new Node0();
#       endif
                } else {
#       if defined(GC)
                        return new (GC_NEW(Node0)) Node0(MakeTree(iDepth-1),
                                            MakeTree(iDepth-1));
#       elif defined(OGC)
#   ifdef BROKEN_SMART_PTRS
     Node left = MakeTree(iDepth-1);
     Node right = MakeTree(iDepth-1);
                          return gc_new Node0(left, right);
#   else
                          return gc_new Node0(MakeTree(iDepth-1),
                                            MakeTree(iDepth-1));
#   endif
#       else
                        return new Node0(MakeTree(iDepth-1),
                                         MakeTree(iDepth-1));
#       endif
                }
        }

        static void PrintDiagnostics() {
#if 0
                long lFreeMemory = Runtime.getRuntime().freeMemory();
                long lTotalMemory = Runtime.getRuntime().totalMemory();

                System.out.print(" Total memory available="
                                 + lTotalMemory + " bytes");
                System.out.println("  Free memory=" + lFreeMemory + " bytes");
#endif
        }

        static void TimeConstruction(int depth) {
                long    tStart, tFinish;
                int     iNumIters = NumIters(depth);
                Node    tempTree;

                cout << "Creating " << iNumIters
                     << " trees of depth " << depth << endl;
               
                tStart = currentTime();
                for (int i = 0; i < iNumIters; ++i) {
#   if defined(GC)
                          tempTree = new (GC_NEW(Node0)) Node0();
#   elif defined(OGC)
                          tempTree = gc_new Node0();
#   else
                          tempTree = new Node0();
#   endif
                        Populate(depth, tempTree);
#          if !defined(GC) && !defined(OGC)
                          delete tempTree;
#   endif
                        tempTree = 0;
                }
                tFinish = currentTime();
                cout << "\tTop down construction took "
                     << elapsedTime(tFinish - tStart) << " msec" << endl;
                    
                tStart = currentTime();
                for (int i = 0; i < iNumIters; ++i) {
                        tempTree = MakeTree(depth);
#   if !defined(GC) && !defined(OGC)
                          delete tempTree;
#   endif
                        tempTree = 0;
                }
                tFinish = currentTime();
                cout << "\tBottom up construction took "
                     << elapsedTime(tFinish - tStart) << " msec" << endl;

        }

        void main() {
                Node    root;
                Node    longLivedTree;
                Node    tempTree;
                long    tStart, tFinish;
                long    tElapsed;

#ifdef GC
// GC_full_freq = 30;
GC_enable_incremental();
#endif

#         ifdef OGC
    GC::SetPolicy(100);
#  endif
                cout << "Garbage Collector Test" << endl;
                cout << " Live storage will peak at "
                     << 2 * sizeof(Node0) * TreeSize(kLongLivedTreeDepth) +
                        sizeof(double) * kArraySize
                     << " bytes." << endl << endl;
                cout << " Stretching memory with a binary tree of depth "
                     << kStretchTreeDepth << endl;
                PrintDiagnostics();
              
                tStart = currentTime();
               
                // Stretch the memory space quickly
                tempTree = MakeTree(kStretchTreeDepth);
#  if !defined(GC) && !defined(OGC)
                  delete tempTree;
#  endif
                tempTree = 0;

                // Create a long lived object
                cout << " Creating a long-lived binary tree of depth "
                     << kLongLivedTreeDepth << endl;
#  if defined(GC)
                  longLivedTree = new (GC_NEW(Node0)) Node0();
#         elif defined(OGC)
                  longLivedTree = gc_new Node0();
#  else
                  longLivedTree = new Node0();
#  endif
                Populate(kLongLivedTreeDepth, longLivedTree);

                // Create long-lived array, filling half of it
                cout << " Creating a long-lived array of "
                     << kArraySize << " doubles" << endl;
#  if defined(GC)
                  double *array = (double *)
    GC_MALLOC(sizeof(double) * kArraySize);
#  else
                  double *array = new double[kArraySize];
#  endif
                for (int i = 0; i < kArraySize/2; ++i) {
                        array[i] = 1.0/i;
                }
                PrintDiagnostics();

                for (int d = kMinTreeDepth; d <= kMaxTreeDepth; d += 2)
{
                        TimeConstruction(d);
                }

                if (longLivedTree == 0 || array[1000] != 1.0/1000)
                        cout << "Failed" << endl;
                                        // fake reference to LongLivedTree
                                        // and array
                                        // to keep them from being optimized away

                tFinish = currentTime();
                tElapsed = elapsedTime(tFinish-tStart);
                PrintDiagnostics();
                cout << "Completed in " << tElapsed << " msec" << endl;
#  ifdef GC
    cout << "Completed " << GC_gc_no << " collections" <<endl;
    cout << "Heap size is " << GC_get_heap_size() << endl;
#  endif
        }
};

main () {
    GCBench x;
    x.main();
}

 

* 컴파일하기
$ g++ -o GCBench GCBench_OGC.cpp -lgc

* 실행하기
$ ./GCBench_OGC
Garbage Collector Test
 Live storage will peak at 8194272 bytes.

 Stretching memory with a binary tree of depth 18
 Creating a long-lived binary tree of depth 16
 Creating a long-lived array of 500000 doubles
Creating 33824 trees of depth 4
        Top down construction took 407 msec
        Bottom up construction took 348 msec
Creating 8256 trees of depth 6
        Top down construction took 351 msec
        Bottom up construction took 348 msec
Creating 2052 trees of depth 8
        Top down construction took 352 msec
        Bottom up construction took 347 msec
Creating 512 trees of depth 10
        Top down construction took 354 msec
        Bottom up construction took 354 msec
Creating 128 trees of depth 12
        Top down construction took 355 msec
        Bottom up construction took 356 msec
Creating 32 trees of depth 14
        Top down construction took 355 msec
        Bottom up construction took 359 msec
Creating 8 trees of depth 16
        Top down construction took 366 msec
        Bottom up construction took 374 msec
Completed in 5332 msec

 

 

 

 

Posted by Scripter
,

 

다음 한 개의 C++ 소스파일 만으로 간단한 Visual C++ 2010 용 MFC 응용프로그램을 만든다.

 

// Filename: MfcHelloApp.cpp
//
//  Compile: cl /nologo /MD /W3 /EHsc /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"  /D "_AFXDLL" /D "_MBCS"  /Yc /FD /c MfcHelloApp.cpp
//
//     Link: link /nologo /subsystem:windows /incremental:no /machine:I386 /out:"MfcHelloApp.exe"  MfcHelloApp.obj
//
//  Execute: MfcHelloApp
//
//  See: %VisualStudio2010_HOME%\Samples\Mfc\general\helloapp\helloapp.cpp
//  Date: 2013. 10. 10.


#include <afxwin.h>
#include <wchar.h>
#include <cmath>

#ifdef MINIMAL

// Stub out non-critical CRT initialization functions
extern "C" void _setenvp() { }
extern "C" void _setargv() { }

// Define a window class derived from CWnd
class CHelloWindow : public CWnd
{
public:
    CHelloWindow()
    {
        CreateEx(WS_EX_CLIENTEDGE,
                      AfxRegisterWndClass(0, ::LoadCursor(NULL, IDC_ARROW),
                      (HBRUSH)(COLOR_WINDOW+1)),
                      _T("Hello World!"),
                      WS_OVERLAPPEDWINDOW,
                      CW_USEDEFAULT,
                      CW_USEDEFAULT,
                      400,       /// CW_USEDEFAULT,
                      220,       /// CW_USEDEFAULT,
                      NULL,
                      NULL,
                      0);
    }
};

#else

// Define a window class derived from CFrameWnd
class CHelloWindow : public CFrameWnd
{
public:
    CHelloWindow()
    { Create(NULL, _T("MFC, 안녕?"), WS_OVERLAPPEDWINDOW, rectDefault); }
    afx_msg void OnPaint();
    DECLARE_MESSAGE_MAP();
};

BEGIN_MESSAGE_MAP(CHelloWindow, CFrameWnd)
    ON_WM_PAINT()
END_MESSAGE_MAP()

void CHelloWindow::OnPaint() {
    CPaintDC dc(this);
    CString msg = "간단한 MFC 응용프로그램";
    dc.TextOut(10, 5, msg);
    wchar_t temp[120];
    double x, y;
    int xpos, ypos;
    x = 1.2;
    y = 5.1;
    swprintf(temp, 100, L"    합:  %wg + %wg = %wg", x, y, x + y);
    xpos = 75;
    ypos = 40;
    dc.TextOut(xpos, ypos, temp);
    swprintf(temp, 100, L"    차:  %wg - %wg = %wg", x, y, x - y);
    ypos += 20;
    dc.TextOut(xpos, ypos, temp);
    swprintf(temp, 100, L"    곱:  %wg * %wg = %wg", x, y, x * y);
    ypos += 20;
    dc.TextOut(xpos, ypos, temp);
    if (y != 0.0) {
        swprintf(temp, 100, L"    몫:  %wg / %wg = %wg", x, y, x / y);
        ypos += 20;
        dc.TextOut(xpos, ypos, temp);
    }
    if (x > 0.0) {
        swprintf(temp, 100, L"멱승:  %wg**%wg = %wg", x, y, pow(x, y));
        ypos += 20;
        dc.TextOut(xpos, ypos, temp);
    }
    if (x > 0.0 && x != 0.0 && y > 0.0) {
        swprintf(temp, 100, L"로그:  log_%wg( %wg ) = %wg", x, y, log(y)/log(x));
        ypos += 20;
        dc.TextOut(xpos, ypos, temp);
    }
}

#endif

// Define an application class derived from CWinApp
class CHelloApp : public CWinApp
{
public:
    virtual BOOL InitInstance()
    {
        m_pMainWnd = new CHelloWindow();
        m_pMainWnd->ShowWindow(m_nCmdShow);
        m_pMainWnd->SetWindowPos(NULL, 0, 0, 400, 220, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
        m_pMainWnd->UpdateWindow();
        return TRUE;
    }
};

CHelloApp HelloApp;  // HelloApp's constructor initializes and runs the app

 

* 컴파일 및 링크하기

 명령창에서 다음 컴파일 명령을 한 줄로 입력한다.

    cl /nologo /MD /W3 /EHsc /O2 /D "WIN32" /D "NDEBUG"  
        /D "_WINDOWS"  /D "_AFXDLL" /D "_MBCS"  /Yc /FD /c 
        MfcHelloApp.cpp  

 

 이어서 다음 링크 명령을 한 줄로 입력한다.

    link /nologo /subsystem:windows /incremental:no /machine:I386  
         /out:"MfcHelloApp.exe"  MfcHelloApp.obj

 

* 실행 결과

 

 

 

Posted by Scripter
,

다음 한 개의 C++ 소스파일 만으로 간단한 Visual C++ 2010 용 Win32 응용프로그램을 만든다.

 

// Filename: ExSdkApp.cpp
//
//  Compile: cl /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D "WIN32" 
//              /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /Gm- /EHsc /GS /Gy /fp:precise 
//              /Zc:wchar_t /Zc:forScope  /Gd /analyze- /errorReport:queue  ExSdkApp.cpp 
//              kernel32.lib user32.lib gdi32.lib
//
//  Execute: ExSdkApp
//
//  See: http://msdn.microsoft.com/en-us/library/vstudio/bb384843(v=vs.100).aspx
//  Date: 2013. 10. 10.

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <cmath>
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

// 전역 변수(Global variables)

// 주요 창의 클래스 명
static TCHAR szWindowClass[] = _T("win32sample");

// 애플리케이션의 주요 창의 제목
/// static TCHAR szTitle[] = _T("Win32 Guided Tour Application");
static TCHAR szTitle[] = _T("Win32 SDK 간단 예제");

 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
    static char szAppName[] = "ExSdk";
    HWND   hwnd;
    MSG    msg;
    WNDCLASSEX  wndclass;
 
    wndclass.cbSize  = sizeof (wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc  = WndProc;
    wndclass.cbClsExtra    = 0;
    wndclass.cbWndExtra    = 0;
    wndclass.hInstance    = hInstance;
    wndclass.hIcon    = LoadIcon (NULL, IDI_APPLICATION);
    wndclass.hCursor  = LoadCursor (NULL, IDC_ARROW);
    wndclass.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName  = NULL;
    wndclass.lpszClassName = szWindowClass;
    wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
 
    RegisterClassEx( &wndclass );
 
    hwnd = CreateWindow(szWindowClass,
                  szTitle,,
                  WS_OVERLAPPEDWINDOW,
                  CW_USEDEFAULT,
                  CW_USEDEFAULT,
                  500,    /// CW_USEDEFAULT,
                  200,    /// CW_USEDEFAULT,
                  NULL,
                  NULL,
                  hInstance,
                  NULL);
 
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
 
    while (GetMessage(&msg, NULL, 0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    HDC          hdc;
    PAINTSTRUCT  ps;
    wchar_t temp[100];
    double x, y;
    int ypos;
 
    switch (iMsg)
    {
        case WM_CREATE:
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            wcscpy_s(temp, 100, L"SDK로 제작한 간단한 Win32 응용프로그램");
            TextOut(hdc, 10, 5, temp, _tcslen(temp));
            x = 1.2;
            y = 5.1;
            swprintf(temp, 100, L"    합:  %wg + %wg = %wg", x, y, x + y);
            ypos = 35;
            TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            swprintf(temp, 100, L"    차:  %wg - %wg = %wg", x, y, x - y);
            ypos += 20;
            TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            swprintf(temp, 100, L"    곱:  %wg * %wg = %wg", x, y, x * y);
            ypos += 20;
            TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            if (y != 0.0) {
                swprintf(temp, 100, L"    몫:  %wg / %wg = %wg", x, y, x / y);
                ypos += 20;
                TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            }
            if (x > 0.0) {
                swprintf(temp, 100, L"멱승:  %wg**%wg = %wg", x, y, pow(x, y));
                ypos += 20;
                TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            }
            if (x > 0.0 && x != 0.0 && y > 0.0) {
                swprintf(temp, 100, L"로그:  log_%wg( %wg ) = %wg", x, y, log(y)/log(x));
                ypos += 20;
                TextOut(hdc, 15, ypos, temp, _tcslen(temp));
            }
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }
 
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

 

* 컴파일하기

 명령창에서 아래의 컴파일 명령을 한 줄로 입력한다.

    cl /Zi /nologo /W3 /WX- /O2 /Oi /Oy- /GL /D "WIN32" 
        /D "NDEBUG" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE"
        /Gm- /EHsc /GS /Gy /fp:precise 
        /Zc:wchar_t /Zc:forScope  /Gd /analyze- /errorReport:queue
        ExSdkApp.cpp 
        kernel32.lib user32.lib gdi32.lib

 

* 실행 결과

 

 

 

 

Posted by Scripter
,

 

1. hello_a.cpp

   첫 번째 예제는 main() 함수 대신 wmain() 함수를 쓰는 예제이다.

wmain 함수의  두 번째 파라미터를 const char *argv[]) 로 하는 대신에 const wchar_t *argv[] 로 해야 하며, 인자로 받은 문자열을 부동소수점수로 변환하기 위해  _wtof(wchar_t[]) 함수를 쓰고 있으며, 한글 출력을 위해 stdio.h 의 printf() 함수를 그냥 쓰면 된다.
wchar_t[] 타입의 문자열을 prntf() 함수로 출력하기 위해서는 포매터 %s 대신 %ws 를 써야 한다.
만일 #include <iostream> 구문을 생략하면, 컴파일 시 printf(), _wtof(), pow(), log() 함수들을 찾지 못하는 에러가 난다. 
 

// Filename: hello_a.cpp
//
//  Compile: cl /EHsc hello_a.cpp
//  Execute: hello_a [number1] [number2]

#include <iostream>

int wmain(int argc, const wchar_t *argv[])
{
    for (int i = 0; i < argc; i++) {
        printf("%d: %ws\n", i, argv[i]);
    }

    if (argc == 3)
    {
        double x;
        double y;
        x = _wtof(argv[1]);
        y = _wtof(argv[2]);
        printf( "  %s: %g + %g = %g\n", "합", x, y, x + y);
        printf( "  차: %g - %g = %g\n", x, y, x - y);
        printf( "  곱: %g * %g = %g\n", x, y, x * y);
        if (y != 0.0) 
        {
            printf( "  몫: %g / %g = %g\n", x, y, x / y);
        }
        if (x > 0.0) 
        {
            printf( "멱승: %g**%g = %g\n", x, y, pow(x,y));
        }
        if (x > 0.0 && x != 1.0 && y > 0.0) 
        {
            printf( "로그: log_%g( %g ) = %g\n", x, y, log(y)/log(x));
        }
    }

    return 0;
}

 

/*
Execute & Output:
Prompt> hello_a 1.2 5.4
0: hello_a
1: 1.2
2: 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222
멱승: 1.2**5.4 = 2.67657
로그: log_1.2( 5.4 ) = 9.24959
*/

 

 

2. hello_b.cpp

   두 번째 예제는 main() 함수 대신 _tmain() 함수를 쓰는 예제이다. Visual C++ 에서 _tmain 은 의 유무에 따라 wmain() 이나 main() 으로 바꾸어주는 일종의 매크로이다.

_tmain() 함수는 두 번째 파라미터를 const wchar_t *argv[]) 로 하는 대신에 const char *argv[] 로 해야 하며, 명령줄에서 실행 시에 인자로 받은 문자열을 부동소수점수로 변환하기 위해  atof(char[]) 함수를 쓰고 있으며, 한글 출력을 위해 stdio.h 의 printf() 함수를 그냥 쓰면 된다.
char[] 타입의 문자열을 prntf() 함수로 출력하기 위해서는 포매터 %s 를 그대로 쓰면 된다.
만일 #include <iostream> 구문을 생략하면, 컴파일 시 pow(), log() 함수들을 찾지 못하는 에러가 난다. 
 

// Filename: hello_b.cpp
//
//  Compile: cl /EHsc hello_b.cpp
//  Execute: hello_b [number1] [number2]

#include <iostream>
#include <atlstr.h>   // required for  _tmain()

int _tmain(int argc, const char *argv[])
{
    for (int i = 0; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }

    if (argc == 3)
    {
        double x;
        double y;
    x = atof(argv[1]);
    y = atof(argv[2]);
       printf( "  %s: %g + %g = %g\n", "합", x, y, x + y);
       printf( "  차: %g - %g = %g\n", x, y, x - y);
       printf( "  곱: %g * %g = %g\n", x, y, x * y);
        if (y != 0.0) 
        {
            printf( "  몫: %g / %g = %g\n", x, y, x / y);
        }
        if (x > 0.0) 
        {
            printf( "멱승: %g**%g = %g\n", x, y, pow(x,y));
        }
        if (x > 0.0 && x != 1.0 && y > 0.0) 
        {
            printf( "로그: log_%g( %g ) = %g\n", x, y, log(y)/log(x));
        }
    }

    return 0;
}

/*
Execute & Output:
Prompt> hello_b 1.2 5.4
0: hello_b
1: 1.2
2: 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222
멱승: 1.2**5.4 = 2.67657
로그: log_1.2( 5.4 ) = 9.24959
*/

 

 

3. hello_c.cpp

   세 번째 예제는 C 언어에서도 통하는 전형적인 소스이다.Visual C++ 에서는 stdio.h 대신 iostream 을 인클루드해도 된다.

만일 #include <iostream> 구문을 생략하면, 컴파일 시 printf(), atof(), pow(), log() 함수들을 찾지 못하는 에러가 난다. 
 

// Filename: hello_c.cpp
//
//  Compile: cl /EHsc hello_c.cpp
//  Execute: hello_c [number1] [number2]

#include <iostream>

int main(int argc, const char *argv[])
{
    for (int i = 0; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }

    if (argc == 3)
    {
        double x;
        double y;
        x = atof(argv[1]);
        y = atof(argv[2]);
        printf( "  %s: %g + %g = %g\n", "합", x, y, x + y);
        printf( "  차: %g - %g = %g\n", x, y, x - y);
        printf( "  곱: %g * %g = %g\n", x, y, x * y);
        if (y != 0.0) 
        {
            printf( "  몫: %g / %g = %g\n", x, y, x / y);
        }
        if (x > 0.0) 
        {
            printf( "멱승: %g**%g = %g\n", x, y, pow(x,y));
        }
        if (x > 0.0 && x != 1.0 && y > 0.0) 
        {
            printf( "로그: log_%g( %g ) = %g\n", x, y, log(y)/log(x));
        }
    }

    return 0;
}

/*
Execute & Output:
Prompt> hello_c 1.2 5.4
0: hello_c
1: 1.2
2: 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222
멱승: 1.2**5.4 = 2.67657
로그: log_1.2( 5.4 ) = 9.24959
*/

 

 

4. hello_d.cpp

   네 번째 예제는 C 언어에서도 통하는 전형적인 소스를 조금 변형하였다. 컴솔 출력 함수 printf() 대신 wprintf() 를 사용하였다. 이 경우 문자열 상수룰 L"........" 처럼 L을 선두에 붙여 하며, 한글을 출력하기 위해서는 문자열 포맷터도 %s 대신 대문자 S를 사용한 %S 로 해야 한다. 

만일 #include <iostream> 구문을 생략하면, 컴파일 시 printf(), wprintf(), atof(), pow(), log() 함수들을 찾지 못하는 에러가 난다. 
 

// Filename: hello_d.cpp
//
//  Compile: cl /EHsc hello_d.cpp
//  Execute: hello_d [number1] [number2]

#include <iostream>

int main(int argc, const char *argv[])
{
    for (int i = 0; i < argc; i++) {
        printf("%d: %s\n", i, argv[i]);
    }

    if (argc == 3)
    {
        double x;
        double y;
        x = atof(argv[1]);
        y = atof(argv[2]);

        wprintf( L"  %S: %g + %g = %g\n", "합", x, y, x + y);
        wprintf( L"  %S: %g - %g = %g\n", "차", x, y, x - y);
        wprintf( L"  %S: %g * %g = %g\n", "곱",x, y, x * y);
        if (y != 0.0) 
        {
            wprintf( L"  %S: %g / %g = %g\n", "몫", x, y, x / y);
        }
        if (x > 0.0) 
        {
            wprintf( L"%S; %g**%g = %g\n", "멱승", x, y, pow(x,y));
        }
        if (x > 0.0 && x != 1.0 && y > 0.0) 
        {
            wprintf( L"%S; log_%g( %g ) = %g\n", "로그", x, y, log(y)/log(x));
        }
    }

    return 0;
}

/*
Execute & Output:
Prompt> hello_d 1.2 5.4
0: hello_d
1: 1.2
2: 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222
멱승; 1.2**5.4 = 2.67657
로그; log_1.2( 5.4 ) = 9.24959
*/

 

 

5. hello_e.cpp

   다섯 번째 예제는 인수 없는 main() 함수를 사용하였다. 인수가 없는 대신 #include <atlstr.h> 하고 CommandLineToArgvW() 함수를 사용하면 명령줄에서 실행 시에 넣어준 옵션 인자들을 받아 처리할 수 있다.

 여기서도 앞의 네 번째 예제 처럼, 컴솔 출력 함수 printf() 대신 wprintf() 를 사용하였다. 이 경우 문자열 상수를 표현할 때 L"........" 처럼 L을 선두에 붙여야 하며, 한글을 출력하기 위해서는 문자열 포맷터도 %s 대신 대문자 S를 사용한 %S 로 해야 한다. 

만일 #include <iostream> 구문을 생략하면, 컴파일 시 printf(), wprintf(), atof(), pow(), log() 함수들을 찾지 못하는 에러가 난다. 

 

// Filename: hello_e.cpp
//
//  Compile: cl /EHsc hello_e.cpp
//  Execute: hello_e [number1] [number2]

#include <windows.h>

#include <iostream>
#include <atlstr.h>   // for CommandLineToArgvW()

int __cdecl main()
{
    LPWSTR *szArglist;
    int nArgs;

    szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
    if ( NULL == szArglist )
    {
        wprintf(L"CommandLineToArgvW failed\n");
        return 0;
    }
    else {
        for (int i = 0; i < nArgs; i++) {
            printf("%d: %ws\n", i, szArglist[i]);
        }
    }

    if (nArgs == 3)
    {
        double x;
        double y;
        x = _wtof(szArglist[1]);
        y = _wtof(szArglist[2]);
        wprintf( L"  %S: %g + %g = %g\n", "합", x, y, x + y);
        wprintf( L"  %S: %g - %g = %g\n", "차", x, y, x - y);
        wprintf( L"  %S: %g * %g = %g\n", "곱", x, y, x * y);
        if (y != 0.0) 
        {
            wprintf( L"  %S: %g / %g = %g\n", "몫", x, y, x / y);
        }
        if (x > 0.0) 
        {
            wprintf( L"%S: %g**%g = %g\n", "멱승", x, y, pow(x,y));
        }
        if (x > 0.0 && x != 1.0 && y > 0.0) 
        {
            wprintf( L"%S: log_%g( %g ) = %g\n", "로그", x, y, log(y)/log(x));
        }
    }

    LocalFree(szArglist);

    return 0;
}

/*
Execute & Output:
Prompt> hello_e 1.2 5.4
0: hello_e
1: 1.2
2: 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222
멱승: 1.2**5.4 = 2.67657
로그: log_1.2( 5.4 ) = 9.24959
*/

 

 

6. hello_f.cpp

   여섯 번째 예제는 닷넷용 컨솔 Hello 예제이다. 컴파일 시에에 옵션 /clr 을 주어야하며, 닷넷용이므로 #include 구문은 사용하지 못하고 using 구문을 사용하여야 한다. 이 예제에서는 using namespace System; 구문을 사용하였다.

  컴솔에 출력하는 함수도 printf() 함수가 아니라 Console::WriteLine() 함수를 사용하였다. 이 경우에도 문자열 상수를 표현할 때 L"........" 처럼 L을 선두에 붙여야 한다. 

// Filename: hello_f.cpp
//
//  Compile: cl /clr hello_f.cpp
//  Execute: hello_f [number1] [number2]

using namespace System;

int main(array<System::String ^> ^args)
{
    if (args->Length == 0)
        Console::WriteLine(L"Hello, world!");
    else if (args->Length == 1)
        Console::WriteLine(L"Hello, {0}씨!", args[0]);
    else if (args->Length == 2) {
        double x = Convert::ToDouble(args[0]);
        double y = Convert::ToDouble(args[1]);
        Console::WriteLine(L"  합: {0} + {1} = {2}", x, y, x+y);
        Console::WriteLine(L"  차: {0} - {1} = {2}", x, y, x-y);
        Console::WriteLine(L"  곱: {0} * {1} = {2}", x, y, x*y);
        if (y != 0)
            Console::WriteLine(L"  몫: {0} / {1} = {2}", x, y, x/y);
        if (x > 0)
            Console::WriteLine(L"멱승: {0}**{1} = {2}", x, y, Math::Pow(x, y));
        if (x > 0 && x != 1 && y > 0)
            Console::WriteLine(L"로그: log_{0}( {1} ) = {2}", x, y, Math::Log(y)/Math::Log(x));
    }
    return 0;
}

/*
Execute & Output:
Prompt> hello_f 1.2 5.4
  합: 1.2 + 5.4 = 6.6
  차: 1.2 - 5.4 = -4.2
  곱: 1.2 * 5.4 = 6.48
  몫: 1.2 / 5.4 = 0.222222222222222
멱승: 1.2**5.4 = 2.67657075645045
로그: log_1.2( 5.4 ) = 9.24958618840702
*/

 

 

 

Posted by Scripter
,

C++98 에서는 swap 함수를 쓸려면 #include <algorithm> 을 했지만, C++0x 와 C++11 에서는 #include <utility> 로 바뀌었다.

또 빝트인 타입의 데이터를 swap 할 때는 이전 처럼 std::swap(dat1. data2) 하지만, 빌트인 타입이 아닌 데이터를 swap 할 때는 std:: 를 붙이지 않고 swap(data1, data2) 로 해야 한다.

 

Visual C++ 의 cl 로 컴파일할려면 Visual Studio 2008 이상이면 되고. g++ 로 컴파일할려면 g++ 4.5.x 이상이면 된다.

만약 Haskell Platform 에 설치된 g++ 4.5.2 로 컴파일할려면 옵션 -enable-auto-import 를 추가하면 성공작으로 컴파일될 것이다.

 

다음 소스의 컴파일과 실행을 테스트한 환경은

        Visual C++ 2008
        Visual C++ 2010
        Visual C++ 2012
        Visual C++ 2013

         gcc 4.5.2
         gcc 4.5.3
         gcc 4.6.2
         gcc 4.7.0
         gcc 4.8.0
         gcc 4.8.1

이다.

 

 

// Filename: testSwap.cpp
//
//       Test swap functions of C++98 and C++11 specifications.
//
// Compile: cl /EHsc testSwap.cpp
// Compile: g++ -std=c++11 -o testSwap testSwap.cpp
// Compile: g++ -std=c++0x -o testSwap testSwap.cpp
//
// See for detail: http://www.cplusplus.com/reference/algorithm/swap/

#include <iostream>        // std::cout
// #include <algorithm>    // std::swap since C++98
#include <utility>         // std::swap and swap since C++0x
#include <vector>          // std::vector
#include <string>          // std::string

template <typename T>
void printVector(std::vector<T> v)
{
  std::cout << '[';
  for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << " ]\n";
}


int main () {

  int x = 10, y = 20;                      // x:10 y:20
  std::swap(x, y);                         // x:20 y:10

  std::vector<int> foo (4,x), bar (6,y);   // foo:4x20 bar:6x10
  // std::swap(foo, bar);                  // foo:6x10 bar:4x20 since C++98
  swap(foo, bar);                          // foo:6x10 bar:4x20 since C++0x

  std::cout << "foo contains:";
  for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
  std::cout << '\n';

  std::string s1 = "Hello,";
  std::string s2 = "world!";
 
  std::cout << s1 << ' ' << s2 << std::endl;
  std::cout << '\n';

  std::cout << "Swapping two strings..." << std::endl;
  s1.swap(s2);
   
  std::cout << s1 << ' ' << s2 << std::endl;
  std::cout << '\n';
 
  std::vector<int> v1(10, 7);
  std::vector<int> v2(5, -1);
  std::cout << "v1 = [";
  for (std::vector<int>::iterator it = v1.begin(); it != v1.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << " ]\n";
  std::cout << "v2 = [";
  for (std::vector<int>::iterator it = v2.begin(); it != v2.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << " ]\n";
  std::cout << '\n';
 
  std::cout << "Swapping two vectors..." << std::endl;
  v1.swap(v2);

  std::cout << "v1 =";
  printVector(v1);
  std::cout << "v2 = ";
  printVector(v2);

  return 0;
}

/*
Output:
foo contains: 10 10 10 10 10 10

Hello, world!

Swapping two strings...
world! Hello,

v1 = [ 7 7 7 7 7 7 7 7 7 7 ]
v2 = [ -1 -1 -1 -1 -1 ]

Swapping two vectors...
v1 =[ -1 -1 -1 -1 -1 ]
v2 = [ 7 7 7 7 7 7 7 7 7 7 ]
*/

 

 

 

 

 

Posted by Scripter
,

다음 소스는 g++ 4.6.2, g++ 4.8.0, g++ 4.8.1 그리고 Visual Studio 2013 Express 의 cl 로 컴파일됨이 확인되었다.

(g++ 4.5.3 과 Visual Studio 2010 의 cl 로는 range based for 구문 때문에 컴파일되지 않는다.)

 

// Filename: vector_for_loop_01.cpp
//
//      Purpose:  How to use vector types and for loops.
//
// With g++ 4.6 above
// Compile: g++ -std=c++0x -o vector_for_loop_01 vector_for_loop_01.cpp
// Compile: g++ -std=c++11 -o vector_for_loop_01 vector_for_loop_01.cpp
// Execute: ./vector_for_loop_01
//
//   or
//
// With Visual C++ 12
// Compile: cl /EHsc vector_for_loop_01.cpp
// Execute: vector_for_loop_01
//
// See: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    for ( auto &i : v ) {
        std::cout << i << std::endl;
    }
    return 0;
}

/*
Output:
17
12
23
42
*/

 

참고로 위의 소스를 Visual C++ 10.0(즉 Visual Studio 2010 의 C++)의 명령줄 컴파일러 cl 로 컴파일하면 다음의 에러메세지가 나온다.

------------------------------------------------------------------------

Microsoft (R) 32비트 C/C++ 최적화 컴파일러 버전 16.00.40219.01(80x86)
Copyright (c) Microsoft Corporation. 모든 권리 보유.

vector_for_loop_01.cpp
vector_for_loop_01.cpp(27) : error C2143: 구문 오류 : ','이(가) ':' 앞에 없습니다.
vector_for_loop_01.cpp(27) : error C2530: 'i' : 참조를 초기화해야 합니다.
vector_for_loop_01.cpp(27) : error C3531: 'i': 형식에 'auto'가 포함된 기호에는이니셜라이저가 있어야 합니다.
vector_for_loop_01.cpp(27) : error C2143: 구문 오류 : ';'이(가) '{' 앞에 없습니다.

------------------------------------------------------------------------

 

또한 위의 소스를 cygwin 의 g++ 4.5.3 으로 컴파일하면 다음의 에러메세지가 나온다.

--------------------------------------------------------

vector_for_loop_01.cpp: In function ‘int main()’:
vector_for_loop_01.cpp:27:19: error: expected initializer before ‘:’ token
vector_for_loop_01.cpp:30:5: error: expected primary-expression before ‘return

vector_for_loop_01.cpp:30:5: error: expected ‘;’ before ‘return’
vector_for_loop_01.cpp:30:5: error: expected primary-expression before ‘return

vector_for_loop_01.cpp:30:5: error: expected ‘)’ before ‘return’
-----------------------------------------------------------------------

 

 

다음 소스는 g++ 4.5.3 및  Visual Studio 2010 의 cl 로도 컴파일되도록 for 반목문을 수정한 것이다.

 

// Filename: vector_for_loop_02.cpp
//
//      Purpose:  How to use vector types and for loops.
//
// With g++ 4.5 above
// Compile: g++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
// Compile: g++ -std=c++11 -o vector_for_loop_02 vector_for_loop_02.cpp
// Execute: ./vector_for_loop_02
//
//   or
//
// With Visual C++ 10
// Compile: cl /EHsc vector_for_loop_02.cpp
// Execute: vector_for_loop_02
//
// See: http://stackoverflow.com/questions/409348/iteration-over-vector-in-c

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    // for ( auto &i : v ) {
    //     std::cout << i << std::endl;
    // }
    for ( auto it = v.begin(); it != v.end(); it++ ) {
        std::cout << *it << std::endl;
    }
    return 0;
}

/*
Output:
17
12
23
42
*/

 

[참고] --enable-auto-import 에러가 날 때

위의 소스가 HaskellPlatforem 에 설치된 mingw 의 (버전 4.5.2 인) g++ 로 캄파일할 때 --enable-auto-import 에러가 날 때가 있다.

C:\test\mingw>g++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
Info: resolving std::cout  by linking to __imp___ZSt4cout (auto-import)
d:/haskellplatform/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../../mingw32/bin/ld
.exe: warning: auto-importing has been activated without --enable-auto-import sp
ecified on the command line.
This should work unless it involves constant data structures referencing symbols
 from auto-imported DLLs.

 

원인은 디헥토리 D:\HaskellPlatform\mingw\lib\gcc\mingw32\4.5.2  에 있는 라이브러리 파일 libstdc++.dll.a 을 찾지 못해 일어나는 에러인 것 같은데 이를 어떻게 해결해냐 하는가?

 

g++ 로 컴파할 때 옵션 --enable-auto-import 를 주고 해보았다.

C:\test\mingw>g++ --enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp
cc1plus.exe: error: unrecognized command line option "-fenable-auto-import"

옵션이 인식이 안된다, 이러 때는 옵션

               -enable-auto-import   또는  -Wl,--enable-auto-import

르 주면 에러나 경고 없이 컴파일이 잘 된다.

C:\test\mingw>g++ -enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>g++ -Wl,--enable-auto-import -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>vector_for_loop_02
17
12
23
42

 

이제 좀 더 편안한 방법을 찾아 보자.

윈도우즈 명령창에서 doskey 를 이용하여 명령 g++ -enable-auto-import 대신할 명령 s++ 를 생성한다.

C:\test\mingw>doskey s++=g++ -enable-auto-import $*

 

이제 s++ 명령으로 컴파일도 하고 실행도 해본다.

C:\test\mingw>s++ -std=c++0x -o vector_for_loop_02 vector_for_loop_02.cpp

C:\test\mingw>vector_for_loop_02
17
12
23
42

 

명렬창을 열때 미리 저런 doskey 설정을 해도 된다.  윈도우카+R 을 눌러서

 

처럼 입력하고 "획인 버튼을 누른다.  이제 새로 열린 명령창에서 컴파일하여 실행한다,

 

 

명령창을 열 때마다 저런 길다란 옵션을 외워서 쓰기도 번거롭다. 그래서 더 편안한 방법으로 "바로가기 명령창 아이콘"을 바탕화면에 링크시켜 놓는다.

 

이제 바탕화면에 깔린 저 아이콘에 마우스 우측 버튼을 클릭하여 속성을 설정한다. 성정할 부분은 아래의 두 그림 처럼 "대상(T)"과 "시작 위치(S)"이다. ("대상(T)" 부분에 입력할 글자가 길어서 그림을 두 개로 만들었다.)

 

 

 

 

이제 저 바탕화면을 클릭하면 g++ 명령 대신 s++ 명령으로 컴파일할 수 있다.

 

* 참고 자료: http://stackoverflow.com/questions/7742332/purpose-of-enable-auto-import-warning

 

 

Posted by Scripter
,

아래의 소스는 (64 비트) 윈도우 8 에서 Visual Studio 2013 Express 의 명령줄 컴파일러 cl 및 cygwin64 의 컴파일러 g++ 로 테스트되었다. (소스를 저장할 시, Visual C++ 용으로는 KSC5601-1987 인코딩으로 저장하고, cygwin64 의 g++ 용으로는 UTF-8 인코딩으로 저장해야 한글이 정상 출력된다.)

 

vector 타입을 초기화(initializer lists)하는 구문

    vecor<T> v { .... }

또는

   vector<T> v = { ... }

은 C++0x(정확하게는 C++09 이후) 또는 C++11 에서만 지원되는 구문이다.

그러므로 다음 소스는 Visual Studio 2010 이나 g++ 의 버전이 4.4 미만이면 컴파일되지 않는다. Visual Studio 2012 도 최소한 November 2012 CTP 이후라야 컴퍼일된다.
 

        [참고 1] Vector initialization with more values in c++11

        [참고 2] Initializer list not working with vector in Visual Studio 2012?

        [참고 3] C++0x Core Language Features In VC10: The Table

        [참고 4] C++11 Features in Visual C++ 11

        [참고 5] C++0x initialization: Lists

 

// Filename: initializeVector_02.cpp
//
// Compile: cl /EHsc initializeVector_02.cpp
// Execute: initializeVector_02
//
//      or
//
// Compile: g++ -std=c++11  -o initializeVector_02 initializeVector_02.cpp
// Execute: ./initializeVector_02
//
// Date: 2013. 9. 25.

#include <iostream>
#include <vector>
#include <cmath>

template <typename T>
void printVector(std::vector<T> v)
{
    std::cout << "[";
    for (auto it = std::begin(v); it != std::end(v); it++)
    {
        std::cout << *it;
        if ((it + 1) != std::end(v))
            std::cout << ", ";
    }
    std::cout << "]";
    std::cout << std::endl;
}

int main()
{
    std::cout << "Hello, 안녕하세요?" << std::endl;

    std::vector<double> v1 = { 1, 2, 3, 4, 5 };
    std::cout << "v1 = ";
    printVector(v1);

    std::cout << "v2 = ";
    std::vector<double> v2 = { sin(v1[0]), cos(v1[1]), exp(v1[2]), log(v1[3]), pow(2, v1[4]) };
    printVector(v2);

    return 0;
}

/*
Output:
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]
*/

 

* Visual Studio 2012 Express for Windows 8 의 컴파일러 cl 을 사용하여 위의 소스를 컴파일한 경우의 컴파일 에러 메세지

Prompt> cl /EHsc initializeVector_02.cpp
x86용 Microsoft (R) C/C++ 최적화 컴파일러 버전 17.00.50727.1
Copyright (c) Microsoft Corporation. All rights reserved.

initializeVector_02.cpp
initializeVector_02.cpp(34) : error C2552: 'v1' : 이니셜라이저 목록을 사용하여
비집합체를 초기화할 수 없습니다.
        'std::vector<_Ty>' : 기본이 있는 형식은 집합체가 아닙니다.
        with
        [
            _Ty=double
        ]
initializeVector_02.cpp(39) : error C2552: 'v2' : 이니셜라이저 목록을 사용하여
비집합체를 초기화할 수 없습니다.
        'std::vector<_Ty>' : 기본이 있는 형식은 집합체가 아닙니다.
        with
        [
            _Ty=double
        ]

 

* cygwin64 의 (버전 4.8.1 인) 컴파일러 g++ 로 옵션 -std=c++0x 또는 -std=c++11 을 주어 위의 소스를 성공적으로 컴파일하고 실행한 경우

g++ -std=c++0x  -o initializeVector_02 initializeVector_02.cpp

$ ./initializeVector_02
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]

g++ -std=c++11  -o initializeVector_02 initializeVector_02.cpp

$ ./initializeVector_02
Hello, 안녕하세요?
v1 = [1, 2, 3, 4, 5]
v2 = [0.841471, -0.416147, 20.0855, 1.38629, 32]

 

Posted by Scripter
,