C > C++ TIPS

C/C++

デバッグoutput

#define dbg(...) \
 (printf("%s %u @%s:",__FILE__,__LINE__,__func__), \
 printf(" "__VA_ARGS__))
 
int foo_bar(int i)
{
  //static const char __func__[] = "foo_bar"; //(1)
  if(i != 3){
    dbg("i=%d", i);
    i *= i;
  }
  return i;
}
 

プラットフォーム依存

コンパイラ

  • GCC
#ifdef __GNUC__
#if __GNUC__ >= 3 // GCC3.0以上
  • Visual C++
#ifdef _MSC_VER(VC++以外でも定義されている場合あり)
#if _MSC_VER >=1000 // VC++4.0以降
#if _MSC_VER >=1100 // VC++5.0以降
#if _MSC_VER >=1200 // VC++6.0以降
#if _MSC_VER >=1300 // VC2003以降
#if _MSC_VER >=1400 // VC2005以降
#if _MSC_VER >=1500 // VC2008以降
#if _MSC_VER >=1600 // VC2010以降
  • Borland C++
#ifdef __BORLANDC__
  • Cygwin / MinGW
#ifdef __CYGWIN__
#ifdef __CYGWIN32__ // 32bit版Cygwin
#ifdef __MINGW32__  // MinGW(-mno-cygwin指定) 

OS

  • UNIX
#ifdef __unix
or
#ifdef __unix__
  • Linux
#ifdef __linux
or
#ifdef __linux__
  • FreeBSD
#ifdef __FreeBSD__
  • NetBSD
#ifdef __NetBSD__
  • Windows
#ifdef _WIN32 // 32bit
#ifdef _WIN64 // 64bit
#ifdef _WINDOWS // GUI
#ifdef _CONSOLE // CUI
#if (WINVER >= 0x030a) // Windows 3.1以降
#if (WINVER >= 0x0400) // Windows 95/NT4.0以降
#if (WINVER >= 0x0410) // Windows 98以降
#if (WINVER >= 0x0500) // Windows Me/2000以降
#if (WINVER >= 0x0501) // Windows XP以降
#if (WINVER >= 0x0600) // Windows Vista以降

double 範囲

INT_MAX int 型の最大値(≧32767)
INT_MIN int 型の最小値(≦-32767)
UINT_MAX unsigned int 型の最大値(≧65535)
LONG_MAX long 型の最大値(≧2147483647)
LONG_MIN long 型の最小値(≦-2147483647)
ULONG_MAX unsigned long 型の最大値(≧4294967295)
FLT_MAX float 型の最大値
FLT_MIN float 型の正の値の最小値
DBL_MAX double 型の最大値
DBL_MIN double 型の正の値の最小値


Cマニピュレータ

種類 記述 機能
フラグ - 左詰め(省略時は右詰め)
+ '+' '-'符号を表示
(空白) 正の数値の先頭に空白を表示
0 0で桁を埋める
# 出力形式の変換。o : 先頭に 0。x: 先頭に 0x。f, e : 小数点
文字数 数値 文字数
\* 引数で指定された文字数
精度 .数値 小数点以下の桁数。・変換形式が d,i,o,u,x の時 : 最低でも数値分の数字を置く。・変換形式が f, e の時 :小数点以下に数値分の数字を置く。・変換形式が s の時 : 最大表示文字数。. ( .0) 小数を非表示。.* 引数で指定された精度
型指定 h (unsigned) short型 (変換が p の時はポインタ型)
l (unsigned) long型 (変換が p の時はポインタ型)
変換形式 d, i 十進値
o 八進値
x (X) 十六進値
u 符号なし十進値
f 浮動小数点(float, double)
e (E) 指数値
p ポインタ(アドレス)
c 文字(char)
s 文字列
% '%' 自身

C++マニピュレータ

記述 機能
dec 十進値 cout << dec << 100;
oct 八進値 cout << oct << 100;
hex 十六進値 cout << hex << 100;
fixed 固定小数点形式(浮動小数点) cout << fixed << 9.9;
scientific 指数形式(浮動小数点) cout << scientific << 9.9;
showbase 0(8進)または0x(16進)を付加 cout << showbase;
noshowbase showbase をクリア cout << noshowbase;
endl 改行(\n)の挿入 cout << 100 << endl;
ends ヌル文字(\0)の挿入 cout << 'a' << 'b' << ends;

固定小数点形式で出力

#include <iostream>
#include <iomanip>
 
// 表示形式を fixed に設定
cout.setf(ios_base::fixed, ios_base::floatfield);
cout << setprecision(5) << tmp << endl; // 小数点以下5桁で表示
// 表示形式をデフォルトに戻す
cout.setf(0, ios_base::floatfield);
 

scientific形式で出力

#include <iostream>
#include <iomanip>
 
os.setf(ios_base::scientific, ios_base::floatfield);
os.precision(20);
cout << tmp << endl;
cout.setf(0, ios_base::floatfield);
 

数値から文字列への変換

#include <sstream>
inline std::string toString(int n)
{
  std::stringstream stm;
  stm << n;
  return stm.str();
}
 

std::string, to upper/lower

#include <string>
#include <algorithm>
void hoge()
{
  std::string data = “Abc”;
  std::transform(data.begin(), data.end(), data.begin(), ::toupper);
}
 

Check if the variable is INFINITY

double value;
#ifdef MSVC
  if( _finite(value) == 0 )
#else //GNU
  if( !isfinite(value) )
#endif
  {
    // value is INFINITY 
  }
 

時間計測

ヘッダファイル
  • time.h
時間を取得する関数
  • time_t time(time_t *)
  • clock_t clock(NULL)
※time() は1秒単位の精度, clock() の精度は機種に依存しますが大体 1ms 単位程度の精度があるようです.
※clock() の戻り値は,秒以下の単位まで整数型で表せるように適当な整数が掛けられています.その適当な整数とは time.h の中で CLOCKS_PER_SEC という定数として定義されています.ですから, clock() で得られた値を CLOCKS_PER_SEC で割ると秒数が求まります.
※UNIX では短時間に終わる処理の計測に clock() 長時間の処理のときは time() を使うようになるでしょう.Windows の場合は25日弱までなら clock() で計測できそうです.
※clock() で求まる時間と,time(time_t *) で求まる時間とは厳密には異なります.clock() で求まる時間はそのプロセスが消費したプロセッサ時間になります.一方,time(time_t *) で求まる時間は歴時間です.つまり,clock() で求めた時間は実時間とは異なります.(そのプロセスが実行されている間,プロセッサリソースのほぼ100%を占有している場合は,ほぼ実時間になります) time(time_t *) は精度は低いですがプロセスの切り替えに影響されず実時間を取得できます.

で,結局時間を測定するときは以下のようにします.

#include <time.h>
main(){
  clock_t start,end;
  start = clock();
  /*ここに測定したい処理を入れる.*/
  end = clock();
  printf("%.2f秒かかりました\n",(double)(end-start)/CLOCKS_PER_SEC);
}
 

注:time() で時間を取得するときは(変数 t に入れるとする)

t=time(NULL);
time(&t);

の二通りの方法がある.

Windows

メモリ使用量の計測(Windows)

#include <windows.h>
#include <psapi.h>
#pragma comment (lib, "psapi.lib")
{
    PROCESS_MEMORY_COUNTERS memInfo = {0};
    GetProcessMemoryInfo( GetCurrentProcess(), &memInfo, sizeof(memInfo) );
    long memSize = (long)memInfo.PeakWorkingSetSize/1024;
    printf("Used Memory Size: %ld\n",memSize);
}
 
 

Linux

Linux スタックサイズ設定

ulimit -s50000

Intel compiler

Catastrophic error: could not set locale "" to allow processing of multibyte characters

export LC_ALL=C

VC++

stdafx.cpp, stdafx.hを削除

  1. Go to プロジェクトプロパティの構成プロパティ→C/C++ > プリコンパイル済みヘッダ
  2. Change [プリコンパイル済みヘッダーの作成/使用] to "プリコンパイル済みヘッダーを使用しない"
  3. Delete stdafx.cpp, stdafx.h


Windowsアプリケーション実行中のデバッグ出力

#define MYDEBUG
void MyOutputDebugString( LPCSTR pszFormat, ...)
{
#if defined (MYDEBUG) && (_DEBUG)
    va_list	argp;
    har pszBuf[ 256];
    va_start(argp, pszFormat);
    vsprintf( pszBuf, pszFormat, argp);
    va_end(argp);
    OutputDebugString( pszBuf);
#else
    return;
#endif
}
 

VC2005: 他のマシンでプログラム起動時にエラーがでる場合

  1. プロジェクトのプロパティを開く
  2. [構成プロパティ]>[C/C++]>[コード生成]
  3. ランタイムライブラリを「マルチスレッドDLL (/MD)」から「マルチスレッド (/MT)」に設定

VC2005: プロファイル

  1. ソリューション構成をReleaseにする
  2. ソリューションエクスプローラーあたりから右クリックして「ガイド付き最適化のプロファイル」の「インストルメント」を選択
  3. ビルドが完了したら同じメニューから「インストルメントまたは最適化されたアプリケーションの実行」を選択
  4. プロファイル結果のファイルがReleaseフォルダ内にpgc、pgdという拡張子で生成される
  5. Visual Studio 2005コマンドプロンプトを開く
  6. コマンド実行: pgomgr /merge (pgcファイル) (pgdファイル)
  7. コマンド実行: pgomgr /summary (pgdファイル) > hoge.txt
  8. hoge.txtにプロファイル結果が出力される。


その他

正規分布をもつ乱数生成

/*
 * Generate random number using Gaussian distribution
 *
 * -  use Box-Muller transform
 * -  input parameters: average, standard_deviation
 */
double gaussd(double average, double standard_deviation)
{
	double u1, u2, g1, g2, r1, r2;
 
	u1 = (double)rand()/RAND_MAX;
	while( u1 == 0.0 ){ 
		u1 = (double)rand()/RAND_MAX;
	} 
	u2 = (double)rand()/RAND_MAX;
	g1 = sqrt(-2.0*log(u1)) * cos(2.0*PI*u2);
	g2 = sqrt(-2.0*log(u1)) * sin(2.0*PI*u2);
	r1 = standard_deviation * g1 +average;
	//r2 = standard_deviation * g2 + average
	return r1;
}
 

バイナリ形式STLファイル読み込み

// STL形式を入力
void LoadSTLBin(const char *filename)
{
	// STLファイルをオープン
	FILE *fh = fopen(filename, "rb");
	if(fh == NULL) { return FALSE; }
 
	try {
		MQPoint p;
		char buf[128];
		int v_index[3];
 
		// ヘッダ分80バイト読み飛ばし
		if(fread(buf, 80, 1, fh) != 1) throw (1);
 
		// 三角の数の取得
		int triNum;
		if(fread(&triNum, 4, 1, fh) != 1) throw (1);
 
		// 各三角形の情報を取得
		for(int i = 0; i < triNum; i++) {
			// 法線情報12バイトをスキップ
			if(fread(buf, 12, 1, fh) != 1) throw (1);
 
			// 座標値36バイトを取得
			for(int j = 0; j < 3; j++) {
 
				// 座標値の読み込み
				if(fread(&(p.x), 4, 1, fh) != 1) throw (1);
				if(fread(&(p.y), 4, 1, fh) != 1) throw (1);
				if(fread(&(p.z), 4, 1, fh) != 1) throw (1);
				v_index[j] = obj->AddVertex(p);
			}
 
			obj->AddFace(3, v_index);
 
			// 色情報2バイトをスキップ
			if(fread(buf, 2, 1, fh) != 1) throw (1);
		}
	} catch (int errorcode) {
		fclose(fh);
		return FALSE;
	}
 
	fclose(fh);
}
 

GCC コンパイルオプション

-O, -O2, -O3
   最適化を行なう。what is difference?
-g
   デバッグ情報を埋め込む。GNU Debugger (gdb) によるデバッグを可能にする。 
-fbounds-check
   実行時に配列の添字が宣言された添字の範囲に入っているかチェックする。範囲外の要素にアクセスした場合などにメッセージが表示され、デバッグに非常に便利である。ただし、実行速度は遅くなる。 
-funroll-loops
   DO ループのアンロールを行ないパフォーマンスを改善する。 
-c
   ソースファイルをコンパイルし、オブジェクトファイルを出力する。リンクは行なわない。

Fortran

G77

  • g77で入出力関数を使うDLLを作成する場合は、libg2c.aをリンクする。



この日記のはてなブックマーク数
最終更新:2011年05月26日 19:02
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。