トップページ
ひらく | たたむ | ページトップ
↓マウスで反転選択した文字を検索
C
   
ページ内検索 ページ外検索
検索したい文字を入力して
ENTERを押すと移動します。
\n
[ トップページ ]
[ ____CommandPrompt ] [ ____JScript ] [ ____MySQL ] [ ____Cygwin ] [ ____Java ] [ ____Emacs ] [ ____Make ] [ ____Perl ] [ ____Python ] [ ____OpenGL ] [ ____C# ] [ ____StyleSheet ] [ ____C++ ] [ ____Winsock ] [ ____Thread ] [ ____VisualStudio ] [ ____C ] [ ____Win32API ] [ ____Lua ] [ ____PhotoShop ]
ヘッダ検索
___

■ マクロ(Macro)


___

■ C.標準マクロ

DESC ANSI C の規格では標準マクロとして以下のものを用意している
   __FILE__
   __LINE__
   __DATE__
   __TIME__
   __STDC__
定数 1. ANSI C 標準準拠 であることの証明 VisualStudio 固有のもの
    __FUNCTION__
POINT TimeStamp として GUIツールのラベルなどに設定しておくとビルドの時刻がわかり管理しやすい。
    sprintf( buf, "%s %s", __DATE__, __TIME__ );
    SetWindowText( hWnd, buf );
___

■ 制御演算子

___

■ for

POINT 元々 while() 原型だったことを考えれば当然 for()の処理手順 初期化式( i=0; ), 継続条件式( i< N; ), 文 再初期化式( i++ )の順で行われる
___

■ for(int i = 0; i < 3; i++)

ここのint i はこのループ内のみで有効かつ存在 [init] | [test] // 1 回目も test される | [statement] | [increment] for文は縦に並んでいると考えるべき 逆に同じようなことが縦に並ぶ場合は、forで制御できる
___

■ priority

priority 1. () [] -> . 2. !, *, & 3. == != 4. && 5. || 以下の記述は問題ない。

  if ( ptr == NULL || fs == NULL )
  if ( !ptr || !fs )
  &p->nr < -> &( p->nr )
  &p->pro[ p->nr ]
___

■ ビット演算(BitOperation)


  DESC
    bit を立てる
   i | 0x00000001
    bit を調べる
   if ( i & 0x00000001 )
    mask する( 下位4bit )
   if ( i & 0x0000000f )
  TIP
    flag に複数の値( 状態 )を設定したい際に効果的
   stat = STAT_SEL | STAT_CPT;
    bit 演算子も 演算中は 4 byte 整数であつかうようだ( 32bit CPU ならば当然 )
   unsigned short si = 1;
   unsigned int ret = si < <  16;  // ret = 65xxx;

  WARNING
    bit 反転( ~ ), 論理否定( ! )を混乱しないこと

___

■ char のデータを左シフト

//extern float angle[3] = {0.0, 0.0, 0.0}; EXtern float angle[3];//これはOK
___

■ typedef


  DESC
    既存のデータ型( 基本型 )に別名をつける。

  POINT
    typedef YYY XXX;
    [ YYY を XXX と呼ぶ ]と Compiler に知らせる
使いどころは、意味があってわかりやすく短い名前をつける。
    typedef  map<  string, number >  MemberTable;

    MemberTable tbl;
または、環境ごとの型定義の違いを吸収するために使う。 マシンに依存する型を定義することで移植性が高まる。
    // 64bit サイズの整数型を i64 という名前で定義する

    #ifdef  __MSC_VER
    // VisualStudio 環境
    typedef  __int64    i64
    #else
    typedef   int64_t   i64
    #endif


    i64  i;  
namespace に収まる public , private の影響うける さらに Code 内の記述も可能. Block の影響をうける。
    // Scope 内で有効
    typedef Foo Delegator;
    Delegator d;


    // int 型の vector を List と呼ぶ
    typedef std::vector< int> List;
    List v;


    // T 型の Pointer を TPtr と呼ぶ
    typedef T * TPtr;


    typedef char *string // char * を string 型として定義
    typedef struct treenode *tree_ptr
    treeptr tnode;
    class bcls{
        typedef unsigned int UINT; // bcls name空間で有効
    }

     // ふたつ 定義することも可能.
    typedef typedef char TCHAR, *PTCHAR;

    // int 型のポインタを intptr と別名をつける
    typedef int *intptr;

    // 別名なので型チェックは元の型と同じ
    void func ( int *);
    intptr ip;
    fucn( ip );
少し厳密に. 記憶クラス指定子が [ typedef ] である宣言は Object の宣言ではなく, 型に対しての名前( 識別子 )をつける 識別子は [ typedef 名]と言う. POINT 新しい型の定義ではなく [ 既存型の同義語 ]を生成するにすぎない "基本型" は言語ごとに決まっている そのため 同一名で 2 回定義すると怒られる ( コンパイラはどれを参照すべきかわからない ) error C2371: 'T' : 再定義されています. 異なる基本型です
       typedef struct {
         float f;
       } T;

       typedef struct {
         int i;
       } T;
typedef した オリジナル型とは互換可能 別名にすぎないので元の型が int ならば, 比較演算子を利用できる。
    #include< windows2.h> 

    SOCKET  s = 2;

    int i = s + 10;

    // 12
    printf( "%d\n", i );

Tag( 名札 ) のない Enum, Struct, Union はすべて Uniq な型を指定 typedef Tset::Bar DEPRECATED Bar;
___

■ 無名共有体.union


  DESC
    cpp 固有
    名前をもたない共有体
    [ object をもたず ] に変数にアクセス可能
    内部の変数は 共有体として働く( メモリを共有 )
    global 変数 無名共有体は static を宣言する static union { int foo, int bar };
    union は cmp に {} の 変数は メモリを共有してねと通知する
    union を宣言することで, 同一の mem 領域に mapping される.
    union 変数の Address 位置から順番に set されるようす.


    union {
      {
        float x;
        float y;
        float z;
      }
      vector3 v;
    };
POINT union は最もサイズの大きい obj に合わせられる
  typedef union uTEST
  {
    long num;
    int d;
    char s[4];
    char c;
  }test;

  test u;
  memset( &u, 0, sizeof(test) );
  u.s[0] = 'a';
  u.c = 64;    // 残りの bit は操作されないことになる.
  memDump( (int *)&u, sizeof(test) );
___

■ 前方宣言(ForwardDeclare)

DESC Compiler に class の symbol の存在を知らせる Class 型だけを記述する header は前方宣言のみでよい POINT Compiler の視点でみると case で ForwardDeclare すればいいかわかる Source を見て, Compile できれば問題なし
     // OK ( ptr (adr) を 代入するので, Foo の構造は知らなくて OK  )
    void func( Foo &f );
    void func( Foo *f );

    // ERROR ( CopyCtor が走るので, Foo の構造を知る必要がある. )
    void func( Foo f );
まとめ Object の構造( mem )を知りたいとき以外は, ForwardDeclare を使おう. TIP header 内では 積極的に利用することで, 相互依存を避ける WARNING cls mem は 定義後でないと使えない -> あたりまえ ( struct 型の定義は 相対 Address を指定するもの ) 2. cls 継承も 先に bcls が定義されている必要あり -> これ理由わからん WARNING 定義が必要な場合は ERROR

    // ERROR
    //    incomplete type is not allowed
    std::vector<  struct foo > v;

    // OK
    std::vector<  struct foo *> v;


    // ERROR
    //    object size がわからないとメモリを確保できない
    struct foo f;



    // A という class があるよ
     class A;

    class B
     {
      A objA;
      const A &getA();
     }

      // A 定義
      class A
      {
      }

___

■ Pointer(ポインタ)


  DESC
    アドレスを格納する変数 [ 可変 ]

  POINT
    配列は わりあてられた領域を指す定数 [ 固定  ]
    // 以下は処理系依存らしい.
    char **tt = {"boo", "foo", "woo"};


___

■ void.ポインタ

void * とは どこかのアドレスを指すポインタ を意味する func(void *) とあれば、何かしらのポインタがくれば それで十分ということになる
___

■ ポインタの算術演算

ポインタは 加算, 減算ができる。
    int a[] = {1,2,3};
    int *i = a;

    // 1 要素すすめる
    i += 1;
    
    // 1 要素もどる
    i -= 1;

      

___

■ [ any ptr -> int ]への妥当性

( 表現できる十分大きな 整数型にいれること )
___

■ PreProcessor


___

■ undef

#define している変数を解除するマクロ展開されなくなる 二重定義の警告もでなくなる
___

■ ## : token 連結演算子

DESC token を連結する演算子 [ ## ] macro のみで有効 A ## B -> AB
    #define FOO( x ) FOO_## x
___

■ Define

DESC C PreProcessor により 文字列を置換する 置換するだけなので, 書き方は色々 sensitive ( MAX != max ) namespace 関係なし( -> 置換なので当たり前 ) つかいみち
    // data の "意味つけ" 名前をつける
    #define PI 3.14f


    // 一般化した別名( 置換えを想定 )
    //  変数としての役割
    #define NEW new
    #if _DEBUG
    # define NEW new( __FILE__, __LINE__)   // Debug 情報を仕込む
    #else
    # define NEW new
    #endif
# 引数つきマクロ # 条件, fall_back 処理 #define myassert( cnd, fall_back ) if ( !(cnd) ) { fall_back; } myassert( i == 0, return ); myassert( strcmp("foo" == s ) == 0 , return 0 ); // 環境ごとの違いを吸収する。 #define FASTCALL __fastcall #define ALIGN(n) __declspec(align(n))

    #define の連結記号は \ が行単位ゆえに空白の行でも \ が必要

    #define FUNC(cnd, fall_back) \
    if ( cnd ) {  \
      fall_back;  \
    }
   // 再定義 は WARNING
   #define PI   3.14
   #define PI   3.1

    // typedef の重複はエラー
    typedef unsigned char foo;
    typedef unsigned short foo;
POINT define の NEST OK PreProcessor の立場はこれ 置換対象があれば, 置換し続ける define の中で #define symbol の使用は OK

  #define TEST( d ) (int)( (d + d + d) / 3.0f )
  # define pi( exp ) printf( #exp" = %d     FILE: %s\n", exp, __FILE__  )

  // TEST(100) = 100     FILE: main.cpp
  // printf( "TEST(100)"" = %d     FILE: %s\n", (int)( (100 + 100 + 100) / 3.0f ), "main.cpp" );
  pi( TEST(100) );


  #define NEW(heap) NEW_IMPL(heap, 0, 0, 0)

typedef は namespace 有効 {} block 内でも OK POINT
  // if()文の中でマクロを使用した際にエラーを起こさない為
  #define MY_MESS(mess) do{ fprintf(stderr, mess);}while(0)
___

■ 定数(Literal)


  DESC
      定数 ( < -> 変数 )
      左辺になれない値( Object )

    意味としては [ 文字で表現された ]などの意味がある
    Comuter では 定数 という意味になるらしい


      "foo" : 文字列リテラル
      2222  : 数値リテラル
TIP // 文字列 Literal は Compiler 時に連結できるので // 長い文字列を複数行にかくときに便利 // SPC, 改行を SKIP してくれる { const char buf[] = "TM Revolution " "Evolution " "The End Of Genesis " "Turbo TypeD"; printf( buf ); } // これも OK strcmp(str, "foo""bar") 定数を LL ( long long ) にする xxxf と同じ
    // Long 型の領域を確保して 10 をセット
    10L
___

■ 変数


  POINT
    プログラム全体で定義はちょうど一つでなければならない

    しかしそれを参照する宣言はいくつあってもOK
    同じ変数の定義が複数あるのもおかしいし
    一つもないのもエラー


      定義 : mem 領域を割り当てること
      宣言 : 型の指定 -> cmp にこの名前のラベルに対して, サイズを教える

  POINT
    変数とは 名前の付けられた メモリ領域のこと。



外部定義 (external definition)
  int x=5;のように 初期設定付きで記述されたもの.
  (紛らわしいですがこの 「外部(external)」はexternとは異なり
  「すべての関数の外部で定義されたもの」という意味です)
  メモリが割り当てられて初期値がセットされます.

 Extern 宣言 (extern declaration)
  extern int x;
  のように extern付きで記述されたもの
  メモリは割り当てられません.
  関数の外部にも内部にも使える



  extern int gFoo;

  int func()
  {
    // File 名 Scope になる
    //  定義ではなく参照
    extern int gBar;
  }
仮定義 (tentative definition) int x; のように初期設定も externもなしで記述されたもの. これはプログラム全体のどこかに外部定義があればextern宣言として振る舞い, なければ外部定義になる また,同じ大域変数の仮定義が 複数あっても良いが それらは同じメモリ領域を参照する
___

■ global 変数

static領域 に確保される TIP stack の大きさは有限 大きな配列を使用すると、stack が不足してプログラムが誤動作する その場合はstatic 領域におく
___

■ 構造体(Struct)


___

■ struct foo

{ int a; // 宣言にすぎない -> ERR: fooObj.bar.b struct test{ int b; int c; }; // 定義 struct test{ int b; int c; }obj; // 無名でも良い struct { int b; int c; }obj; POINT 後に変数の並びがない構造体宣言は, メモリ割り当てはされない。
    struct ivec2{
      int x;
      int y;
    };

   struct {
    int x;
    int y;
   }x;   // x 構造体変数 mem 割り当て
___

■ 構造体の代入

構造体は代入ができる。 そのため、引数の値渡し、関数の戻り値として利用できる。
    // vec3 構造体の定義
    struct vec3 {
      float x, y, z;
    };     

    struct vec3 v1, v2;
    v2 = v1;

    struct vec3 v3 = add( v1, v2 );
___

■ 引数


___

■ main関数の引数

argc に引数の数、argv に引数文字列のポインタの配列がセットされる。
    int main( int argc, char *argv[] ) {
      for( int i=0; i< argc; i++ ){
        print ( "index %d  %s\n", i, argv[i] );
      } 
    }
WARNING 引数にはプログラム名も含まれるので、意味のある引数は index 1 からになる。
    // 0   main.exe
    // 1   1
    // 2   2
    // 3   3
    // 4   d:/tmp/test.txt

    main.exe   1  2  3  "d:/tmp/test.txt"
___

■ 可変引数

void log(const char *sect, const char *format, ...); void print( const char *fmt, ... );
___

■ C++からの仕様の取り込み


___

■ const

型に対する修飾子のひとつ。
    const int i = 0;
REFERENCE const
___

■ キャスト(Cast)


  DESC
     整数のかくあげ

    整数を扱う式で, int として表現できる型は int に変換
    char, short, bf, enum -> [ int | uint ]

___

■ 算術変換

      整数同士の式は unsigned が常にかつ
     整数同士の式は int として表現できる型は int に変換
     浮動小数の式は 十分な大きさの最小の型に格上げされる
    unsigned int n = 10;
    int i = 0;

    for( i=0; i< n; i++ ){

    } 

___

■ 代入時の自動的型変換

    int b = 7;
    float a = b;
POINT キャストとは malloc などでデータ領域を確保し、 その領域をある型の配列などとして 使用するために使うのが主たる使用法
___

■ 暗黙の型変換

[ == ] は演算の一種暗黙の型変換が起こる 「int型→float型→int型の場合」はbug の可能性あり 有効桁数が少ないfloat型に変数aの「123,456,789」大きなint型の値を代入すると、 有効桁数不足から誤差が発生結果変数b「1.23456792×10の8乗」という値 WARNING int型とfloat型間の代入では誤差の発生が付き物 コンパイルエラーにはならない INVALID : 不定
___

■ 関数型( 関数ptr )の考察

DESC 関数 ptr はキャストすれば
___

■ ptr < -> integer

POINT int -> any ptr への変換は OK DESC integer 型式は ptr と +- 可能 2. ptr -> int( ptr 表現可能な大きさ ) -> ∵ ( ptr も 整数値 ) 3. int -> ptr 4. aPtr < -> bPtr 4. 同一型 obj への ptr の相互変換 { fooObj *a, *b; a = b; } 5. func ptr 同士の変換 int *p; p + 5; // ptr を int 型に格納( cast いるかも ) { int a = 7; int p = (int)&a; printf("%d\n", *((int *)p)); } // 異なる obj 間の ptr 変換 ( mem 配置の整合性があえば OK ) { typedef struct { int a; int b; }base; typedef struct { int a; int b; int c; }derive; { base b = { 4, 5 }; derive *d = (derive *)&b; printf( d->a ); printf( d->b ); } // funcPtr 間の変換 { int (*fPtr)(); void (*gPtr)(int, int); // できない ? fPtr = gPtr; }
___

■ int < -> float

DESC float -> int : 少数部分むし. INVALID( int で表現不能 | -float -> uint ) int -> float : 表現可能な近似値
___

■ float < -> double

DESC float -> double : NOCNG double -> float : 表現可能な近似値. INVALID( float の範囲外 からの変換 )
___

■ Array



    // 初期化方法.
    int a = 7;
    int array[] = {a, a, a};


    // コンパイル時にサイズが指定できればよい
    const int nr = 8;
    int temp[ nr ];
配列 == 1次元Table DESC Table とはあるObject をID(数字)で表現したもの char *name_t[] = {"foo", "bar", "hoge"};
___

■ 2次元Array

DESC data[2][4] は [4] の塊が連続しているのと同義 matrix44[4][4] == data16[16] は行優先で読むのと同じ
___

■ 演算子(operator)


error:
 ptr[k];

OK:
(*ptr)[k]
___

■ 3項演算子

a = a > b? a : b; 返り値をうけとるべき
___

■ 真偽.否定演算子

DESC 0 : 偽 1 : どれか bit がたっている TIP sizeof( bool ) = 1, sizeof( int ) = 4, // ( VC, gcc ) WARNING != 1 でない点に注意
___

■ 逆参照演算子

DESC [*]
      typedef void (*func)();
      void foo()
      {
  ...
      }
      func f = foo;
      (*f)();  // 逆参照
___

■ 桁あふれ(overflow)


  DESC
    桁あふれとは扱える数値範囲を超えること。
  
    unsigned char 型は 1byte で 0 - 255 の範囲を扱うので
    +1 をすると 0 になる。

char < -> int 箱にはいらない部分は切り捨てられると考えるとわかりやすい。 Compiler WARNING にもならない
  int a=256
  a[0x00 00 01 00]

  char b=a -> 0
  b[0x-- -- -- 00]
  EX2.
  char a=-1;
  a[0x-- -- -- ff]

  int b = a;
  a[0xff ff ff ff]

  Java
  // [0x0001 0001]
  short s = 257;
  // RET:b 1
  byte b = s;
TIP 単純に mem cp がされるわけではない
___

■ 型(Type)


  DESC
    型とは Address がさすビット列データの意味のこと。
    Object がもつことができる[ 値の集合 ]と, それに適用できる演算を決めるもの


    Computer で扱う Object は変数と定数のみ
    定数は. int 型である

    // 整数とみれば, 64
    010101010

    // char という意味でみれば 'A'
    010101010
___

■ 整数

int が 4byte の場合では, -2億 - 2億 の範囲の値の整数を扱うことができる。 C にある 型は 4 種類
            char  : 1 byte
            int   : ハードウェアが扱う整数
            float
            double
さらに修飾子がついて long short ( 整数型のみ有効 ) int は HW( 計算機によって異なる ) Compiler は HW の仕様にあわせて, int のサイズを決めることができる。 C の仕様では以下の規則しかない。 int のサイズが 4 byte というのも厳密には保障されない。
       short < = int < = long 
WARNING int は掛け算が苦手なので、int の範囲を超えるような掛け算をする場合は float 型をつかう
    // BAD
    int i = 50000;
    printf( "%d\n", i*i );

    // OK
    float f = 50000;
    printf( "%f\n", f*f );
___

■ size_t

POINT 符号なし整数 を typedef したもの そのため厳密には環境ごとで型のサイズがことなる。 32bit 環境ではたいてい unsigned int ( 4byte )
___

■ float

基数表記 0.5を浮動小数点数で表すと、基数が10の場合は5.0×10-1(5.0e-1)、基数が2の場合は1.0×2-1となる。
    1e-6f
WARNING
  float に誤差が発生するため(float という表現) a = 0.1; if( a == 0.1 )
WARNING 扱える値の範囲を大きくしたかわりに 精度を犠牲にしているので 大きな値と小さな値を同時に利用しないこと。 float も int も 4byte なら扱える値は同じ数しかということ。
    float f = 50000;
    float f2 = f*f;

    // 2500000000.000000
    printf( "%f\n", f2 );

    // +1 は精度が足りないため, 丸められる。
    // 2500000000.000000
    f2 = f2 + 1;
    printf( "%f\n", f2 );
カウンタとして利用すると 1600 万あたりで増えなくなる。
    float f = 0;
    int i = 0;
    for( i=0; i< 1024*1024 * 24; i++ ){
      f += 1;
    } 

    // 16777216.000000     25165824
    printf( "%f  %d\n", f,  i );
___

■ boolean とは

定義: false 0: true 未定義 正しい例 if( status_check() ) 理由 zero 比較の結果は簡単に作成できるが、それ以外の値の比較は operation がひとつ増える
___

■ uintptr_t

DESC ptr を 整数に変換する 問題は ptr size が int と同じサイズとは限らないこと 64 bit binaryでは, sizeof(int) = 4, sizeof(void *) = 8 int 型も Compiler により, 64bit 環境では size が異なるらしい GCC : sizeof ( int ) = 8 VS : sizeof ( int ) = 4 DEP C99 stdint.h::intptr_t, uintptr_t TIP 32bit ptr から u64 に変換する際は 上位に 1 bit がはいらないように uintptr_t に変換する WARNING ptr を Int 型に cast していると, 64 bit では 上位 bit がなくなる
  // ERROR
  // 0x80 00 00 00 が負の整数として扱われる
  // 64 bit に 拡.張 されるとき 上位 bit に 1 がはいる
  void *p = (void *)0x80000000;
  uint64_t x = reinterpret_cast<  uint64_t >(p);

  //    OK
  // 上位に 1 bit が入るのを避ける
  uint64_t x = reinterpret_cast<  uintptr_t >( p );
VisualStudio では次のように定義
    #ifdef  _WIN64
    typedef unsigned __int64    uintptr_t;
    #else
    typedef _W64 unsigned int   uintptr_t;
    #endif
___

■ __int64

DESC C、C++における非標準の変数型で、64ビット長の整数を宣言する。 Microsoft C/C++やBorland C++Builder、その他の環境でこの変数型に対応している。 gcc は対応していない。 POINT 非標準の型であるので, Visual C++ 以外の環境では利用できない。 32bit 環境でも利用できる。64bit 環境ではレジスター1本ですむが、32bit環境では2本使う。 内部では32ビット×2で処理される。
    __int64 num;
    num = 0x1122334455667788i64;

    _num$ = -8
    mov DWORD PTR _num$[ebp], 1432778632
    mov DWORD PTR _num$[ebp+4], 287454020

___

■ __int32

DESC __int64 と同じく Visual C++ 固有の 32bit の整数型
___

■ wchar.wchar_t

ANSI C は標準でワイド文字をサポートしている
___

■ MultiByteCharacter.とは

英数字や一部の記号を 8bit ひらかな.漢字を 16 bit で表現 MS-DOS の時代から使われている Shift-JIS を使ったモ−ド
___

■ WideCharacter.とは

1文字表現するのに2バイト用いる文字のこと なぜ Wide 文字ができたか ? 1 Byte だけでは中国語や日本語のような 漢字や記号を多く持つ言語を表せないから. WideCharacter は国際的なアプリケーションの開発には必要な知識 UNICODE も WideChara のひとつ( 一例にすぎない ) ワイド文字の型は wchar_t であらわす // WCHAR.H typedef unsigned short wchar_t; // 実体は unsigned short ワイド文字型で文字列を表現してみましょう ワイド文字として文字列を格納するには、文字列の前にL(Long)プレフィックスを指定する wchar_t wc[] = L"test"; ワイド文字列は、必ず 1文字 2バイトの領域を確保する VC で L"aiueo" とすると utf-16 で Encode される
___

■ symbol(識別子)


  DESC
      mem obj( var, func, enum, typedef, ...) の名前

      var は mem obj のひとつ
    記憶クラス   : 記憶場所の 寿命
  2. type( 型 ) : mem obj 値の意味 -> [01011011] ->(float | int ....)
  3. scope      :
  4. linkage    : link 時の参照 範囲指定


  変数型の Symbol は Address に名前をつけたもの


___

■ リファレンス(Reference)


___

■ IO

___

■ fwrite

SYNTAX size_t fwrite( const void *buf // 書き込みデータのポインタ size_t sz // バイト長さ size_t n // データ数 FILE *fp // FILEポインタ ); RET OK  : 書き込んだデータ個数( バイトではない ) ERROR : nより小さな値 DESC ファイルへ size バイトのデータを n 個書き込み
      static unsigned char data[ 1024 * 512 * 4 ];

      glReadPixels(
                   0, 0,
                   1024, 512,
                   GL_RGBA,
                   GL_UNSIGNED_BYTE,
                   data
                   );

      FILE *fp = fopen( "d:/capture.raw", "wb" );
      fwrite( data, sizeof(data), 1, fp );
      fclose( fp );
___

■ fread

SYNTAX size_t fread( void *ptr, // 格納先の Buffer size_t size, // 1 つの data size size_t nr, // data の個数 FILE *stream // 読みこみ先の stream ); DESC stream ポインタで指定されたストリームから nr 個のデータを読み込み ptr で与えられた場所に格納する 個々のデータは size バイトの長さを持つ WARNING 文字とおり, 指定した Size しかよまないので, printf(); をするときは '\0' を忘れずに REF http://www.linux.or.jp/JM/html/LDP_man-pages/man3/fread.3.html
    {
      char buf[256];
      memset( buf, 0, sizeof(buf) );

      FILE *fp = fopen( "d:/test.txt", "r" );

      // 日本語だと どうなるか TEST
      // ERROR
      //    sizeof(char) == 1 なので [い] しか読まれない
      //    そもそも fgets() のがいいかも
      fread( buf, sizeof(char), 2, fp );

      printf( buf );
      fclose( fp );
    }
___

■ fprintf

SYNTAX fprintf( FILE *, const char *format, ... )
    fprintf( fp, "%32s%4d", n->str, isLeaf );
___

■ string

    #include < string.h>
___

■ strlen

SYNTAX int strlen( const char * ); DESC 文字数をかえす ( Buffer Size ではない ) "\0" はカウントしない
    {
      char buf[256];
      sprintf( buf, "%s", "abc" );
      // RET: 3
      strlen( buf );
    }
WARNING
    strlen の \0 忘れ
    ERROR
      char *p = malloc( strlen(str) );
      // error;
      strcpy(p, str);
___

■ strdup

SYNTAX char *strdup(char *DST, const char *SRC);
___

■ strcpy

SYNTAX char *strcpy(char *DST, const char *SRC); DESC src ( \0 含む )を dst へコピー RET dst の先頭ポインタ
    const char *src = "test";
    int nr = strlen(src);

    char *dst = (char *)malloc( nr+1 );
    strcpy( dst, src );
___

■ strlcpy

SYNTAX size_t strlcpy( char *dst, const char *src, size_t size ); DESC セキュアな strcpy src の指すアドレスから最大で size - 1 バイトの文字列を dst にコピーする。 また dst の指す文字列が必ずヌル文字で終わるようにする。 dst が char 配列の場合に sizeof(dst) を size として指定すればバッファオーバーランしないことが保証される。
    char path[ NR ];
    strlcpy( path, src, NR );
___

■ strchr

SYNTAX char *strchr(const char *str, int c ); DESC 文字列 str から 文字 c を検索してそのアドレスを返す。 c は最初に見つかったアドレスを返す。 後ろから検索するには strrchr を使う。 RET NULL : search が c に含まれない !NULL : str の中の c のアドレス
    if ( strchr( "test.bmp", '.' ) != NULL ) {

    }
___

■ strrchr

SYNTAX char *strrchr(const char *str, int c );
    if ( strrchr( "d:/foo/test.bmp", '/' ) != NULL ) {
      
    }
___

■ strstr

SYNTAX char *strstr( const char *str, const char *search ); DESC 文字列 str から search を検索してマッチした場合はその先頭アドレスを返す search は \0 を含めずに検索する RET NULL : search が str に含まれない str : search が長さ 0 の場合は str がかえる
    char *s = strstr( "test.bmp", ".bmp" );
    // .bmp
    ptintf( "%s", s );
___

■ strncpy

SYNTAX char *strncpy( char *dst, const char *src, size_t n ); DESC 文字型配列 dst に文字列 src を先頭から n 文字コピー dst と src が重なっている場合には動作は未定義 strlen( src ) >= n なら n 文字をコピーするが '\0' の自動付加はしない src : [a][b][c][d][e] dst : [ ][ ][ ][ ] strncpy( dst, src, sizeof(dst)-1 ); dst : [a][b][c][ ]
    // strlen( src ) <   n なら、残りの文字を '\0' で埋める
    src : [a][b]
    dst : [ ][ ][ ][ ]

    strncpy( dst, src, sizeof(dst)-1 );
    dst : [a][b][\0][ ]
  // まとめ
  //    0 で padding して
  //    sizeof(dst) - 1 文字のみ Copy すること


    char dst[4];
    memset( dst, 0, sizeof(dst) );
    
    strncpy( dst, "abcedf", sizeof(dst)-1 );

    // BAD
    //   BufferOverRun
    //::strncpy( dst, "abcedf", sizeof(dst) );


    printf( "%s", dst );
___

■ strtod

SYNTAX double strtod(const char *STR, char **TAIL); float strtof(const char *STR, char **TAIL); RET 0 : Fail !0 : 数値 正しい値が表現可能な値の範囲外であるとき 値の符号に従って 正または負のHUGE_VALを返し errnoにはマクロERANGEの値を格納する。 正しい値がアンダーフローを起こすときには0を返し errnoにはマクロERANGEの値を格納する DESC 文字列を double | float 型に変換して返す。
    {
      char *e;
      char s[32] = "124.5";

      double x = strtod(s, &e);

      if (errno != ERANGE) {
        printf("変換数値=%f\n", x);

        // 間違っていたら何かをさす
        if (*e != '\0') {
          printf("変換不可能部分=%s\n", e);
        }
      }
      else if (x == HUGE_VAL) {
        printf("double値で表現できる値を超えました\n");
      }

      return 0;
    }
sprintf_s と sprintf の違い sprintf_s は書式指定文字列の有効な書式指定文字をチェックしますが sprintf は書式指定文字列またはバッファが NULL ポインタかどうかのみをチェックをする。 いずれかのチェックが失敗した場合 「パラメータの検証」に説明されているように 無効なパラメータ ハンドラが呼び出されます 実行の継続が許可された場合 関数は -1 を返し errno を EINVAL に設定します sprintf_s は 出力バッファのサイズを文字数で指定する長さパラメータを受け取ります バッファが小さすぎて出力テキストを格納できないなら バッファは 空の文字列に設定され 無効なパラメータ ハンドラが呼び出されます snprintf とは異なり sprintf_s では 必ずバッファは null で終わります (バッファ サイズがゼロでない限り) } EX { // Buffer Size = 8 char buf[] = "1234567"; int ret = _snprintf_s( buf, sizeof(buf), sizeof(buf)-1, "foo" ); int ret = _snprintf_s( buf, sizeof(buf), _TRUNCATE, "foo" ); myas( ret != -1, "切り捨てられたけど, ダイジョーブ ?" ); if ( ret == -1 ) { printf( "切り捨てられた\n" ); } else { printf( "%d + 1 文字かきこみました\n", ret ); } }
___

■ jump

    #include < setjmp.h>
通常の関数 の return をさけるために使う
    // longjmp の戻り先を指定する
    int setjmp( jum_buf env )

    int longjmp( jum_buf env, int val )

___

■ time

日付, 時刻 をあつかう
    #include< time.h>
___

■ clock

SYNTAX clock_t clock(); DESC プログラム開始時からの経過時間( msec )をかえす。 秒単位にするには macro `CLOCKS_PER_SEC'. でわる clock_t, time_t は時間をあらわす算術型 RET 単位 machine-dependent macro `CLOCKS_PER_SEC'. 未定義なら (clock_t)`-1'
    clock_t s = clock();

    system( "timeout 3" );

    clock_t dt = clock() - s;

    printf("%d  sec\n", dt / CLOCKS_PER_SEC );
    printf("%d msec\n", dt );
___

■ difftime

SYNTAX double difftime( time_t t2, time_t t1 ) DESC 経過時間( 秒 )をかえす


時間を表す構造体 struct tm
    struct tm {
        int tm_sec;        // 秒
        int tm_min;        // 分
        int tm_hour;       // 時
        int tm_mday;       // 日
        int tm_mon;        // 月( 1月=0 )
        int tm_year;       // 西暦年 - 1900
        int tm_wday;       // 曜日( 日=0 )
        int tm_yday;       // 日(年を通して)
        int tm_isdst;      // サマータイムフラグ
    };
___

■ time

SYNTAX time_t time( time_t * ) DESC 現在の時間をかえす
___

■ asctime

SYNTAX char *asctime( const struct tm *tp ) DESC 文字列表現としてかえす
    time_t t = time( NULL );

    // Sat Jun 23 15:39:46 2012
    printf( "%s\n", asctime( localtime(&t) ) );
___

■ localtime

SYNTAX struct tm *localtime(time_t *CLOCK); DESC convert time to local representation mktime' is the inverse of `localtime'.
___

■ mktime

SYNTAX time_t mktime(struct tm *); DESC convert time to arithmetic representation
___

■ memory

    #include< memory.h> 
___

■ memcpy

SYNTAX void* memcpy( void *dst, const void *src, size_t N); DESC N バイトを src から dst へコピーする。 src と dst の指す領域が重複する場合の処理は未定義 RET dst のアドレス
___

■ memmove

SYNTAX void *memmove( void *dst, // Copy 先 const void *src, // Copy 元 size_t n // コピーバイト数 ); DESC dst の先頭から n 文字分 src をコピーする strcpy()と異なり空文字('\0')を付加しない src を単なるメモリブロックとして扱うため 途中に空文字('\0')も含めてコピーを続ける dst と src が重なっているときの動作は memcpy() では未定義ですが、 このmemmove() では正しくコピー(つまり移動)がされる
___

■ memcmp

SYNTAX int memcmp( const void *buf1, const void *buf2, size_t n ); DESC buf1 と buf2 を先頭から n バイト分比較する 比較は unsigned char としてされる buf1 と buf2 をメモリブロックとして扱うため 空文字 \0 を含んでいても比較を続ける RET > 0 buf1 > buf2 < 0 buf1 < buf2 ==0 buf1 = buf2 POINT 型ごとの内部表現の違いを調べるときにも使える。
    // int < -> float の mem layout の違いがわかる.  -> 0 は同じ  1 は異なる.
    {
        int i = 1;

        // 型変換. ( 01 の並びが変わる ( 表現方法がかわる ) )
        float f = i;

        // 中身を見てみる.
        memDump( &i );
        memDump( &f );


        // ここでも型変換がおきるらしい.
        if ( f == i ) {
          printf( "same\n" );
        }
    }
___

■ memset

SYNTAX void memset( void *adr, int c, size_t n ); DESC buf の先頭から n バイト分 c をセット adr: unsigned char *型にキャストされ、 c: unsigned char型にキャストされる
___

■ malloc

SYNTAX void *malloc( size_t sz ); DESC sz 分のメモリをヒープ領域から確保する。 POINT デバッグ用に malloc をラップする。

    #ifdef _DEBUG
    #  define MALLOC( s ) malloc( s, __FILE__, __LINE__ )
    #else
    #  define MALLOC( s ) malloc( s )
    #endif


    void *p = MALLOC( 128 );



___

■ IO

    #include< stdio.h> 
___

■ printf

SYNTAX %[フラグ][最小フィールド幅][.精度][長さ修飾子]変換指定子 RET 出力した文字数 符号指定. + : [ %+f ] : 常に符号表示 長さ修飾子 l : [ %lb ], : 変換修飾子
    d  : [ %d ]   : 10 進整数
    u  : [ %u ]   : 10 進符号なし整数
    x  : [ %x ]   : 16 進符号なし整数
    s  : [ %s ]   : 文字列
    p  : [ %p ]   : Pointer の値
    f  : [ %f ]   : 小数点形式 浮動小数
    e  : [ %e ]   : 指数形式 浮動小数
指定子 対応する型
  %c     char                 1文字を出力                    "%c"
  %s     char                 文字列を出力                    "%8s", "%-10s"
  %d     int, short           整数を10進で出力                "%-2d","%03d"
  %u     unsigned int,
         unsigned short       符号なし整数を10進で出力        "%2u","%02u"
  %o     int, short,
         unsigned int,
         unsigned short       整数を8進で出力                 "%06o","%03o"
  %x     int, short,
         unsigned int, 
         unsigned short       整数を16進で出力                "%04x"
  %f     float                実数を出力                      "%5.2f"
  %e     float                実数を指数表示で出力            "%5.3e"
  %g     float                実数を最適な形式で出力          "%g"
  %ld    long                 倍精度整数を10進で出力          "%-10ld"
  %lu    unsigned long        符号なし倍精度整数を10進で出力  "%10lu"
  %lo    long, unsigned long  倍精度整数を8進で出力           "%12lo"
  %lx    long, unsigned long  倍精度整数を16進で出力          "%08lx"
  %lf    double               倍精度実数を出力                "%8.3lf"
精度 浮動小数の小数の桁数を指定する。

    printf( "%.2f" )
     char *p

    // 0xaabbccdd;
    printf( "%#02x ", p[i] );  

    // AABBCCDD;
    printf( "%#02X ", p[i] );  

    int i = 10;
    [ %04d ] : 桁数表示
WARNING 最小フィールド幅は最小の幅を指定するだけ。 幅よりも大きい値がくると幅数がふえる
    int i = 2;

    // " 2 2"
    printf( "%2d%2d", i );
    
    i = 123;
    // "123123"
    printf( "%2d%2d", i );
std::cout を利用すれば format 演算子は必要はない。
    #include< iostream>
    std::cout < <  i <  " " < <  f < <  " " p < <  endl;
      assert( !printf("name: %s", s.c_str()) && i != N );
"r", "rb" を指定するのは [\n] がきたときに MS 用に \r\n と変換するため ( これだけの違い )
___

■ sprintf

SYNTAX int sprintf( char *str, const char *format, ... ); RET OK : strに格納した文字数(最後の'\0'は除く) DESC 書式 format にしたがい printf 関数と同様の変換をした出力を文字列 str にセットする。 WARNING %X の場合は 整数を引数とするため char -> int -1 -> 0xFFFF FFFF // 4 Byte 整数に CAST される char c; sprintf( buf, "%X", c ); WARNING format によって簡単にバッファーオーバーランを起こすため 書き込み文字列指定 sprintf を使うこと。 REFERENCE _snprintf_s
    char buf[256];
    void log( const char *msg ) {
      sprintf( buf, "%s", msg );
    }
___

■ vsnprintf_s(_vsnprintf_s)

SYNTAX int vsnprintf_s( char *buf, size_t sz, // バッファサイズ size_t count, // 書き込む文字数 ( 最後の \0 を含めない ) const char *format, va_list argptr ); RET N : 書かれた文字数 ( \0 を含めない ) -1 : エラー または count 以上の文字が切り捨てられた。 DESC vsprintf のセキュア版。 C4996 が出る場合は これを利用する。 POINT vsnprintf_s と _vsnprintf_s は同じ。 ( _vsnprintf_s は下位互換のため残している )
    char buf[ 256 ];
    _vsnprintf_s( buf, sizeof(buf), sizeof(buf)-1, "test %s", __FILE__ );
___

■ vsnprintf

SYNTAX int vsnprintf( char * restrict s, size_t n, const char * restrict format, va_list arg );
___

■ vsprintf(vswprintf)

DESC 可変引数リストをもつ sprintf printf のカスタマイズ版をつくる。
  void print( const char *form, ... )
  {
    char buf[1024];

    va_list arg;
    va_start( arg, form );
    vsprintf( buf, form, arg );
    va_end(arg);

    printf ( "INFO: %s\n", buf );

  }

  void main()
  {
    print( "result = %d", 777 );
    print( "msg = %s", "test" );
  }

___

■ vprintf

SYNTAX vprintf( const char *format, // 書式文字列 ... // 可変引数 ); DESC 可変引数と書式文字列従って標準出力へ書き出す RET N : 出力した byte 数 < 0: 出力した byte 数
    void p(const char *fmt, ...) 
    {
      va_list arg;

      va_start(arg, fmt);
      vprintf(fmt, arg);
      va_end(arg);

      char buf[256];
      gets(buf);
    }
___

■ fflush

SYNTAX fflush DESC バッファリングされた出力を強制的に出力する
    fflush( stdout );
___

■ fopen

SYNTAX FILE *fopen(const char *FILE, const char *MODE); DESC
___

■ fseek

SYNTAX int fseek( FILE *FP, // File Pointer long OFFSET, // 検索位置からの offset int WHENCE // 検索開始位置 ) DESC FILE Pointer の読み込み位置を移動する

    FILE *fp = fopen( "test.txt", "r" );

    // 先頭 から offset 0
    fseek( fp, 0, SEEK_SET );
    long s = ftell( fp );


    // 末尾 から offset 0
    fseek( fp, 0, SEEK_END );
    long e = ftell( fp );

    // file size を取得
    int sz = e - s;
    printf( "file size %d\n", sz );

    // データを読む場合は先頭にもどすこと
    fseek( fp, 0, SEEK_SET );

    char *buf = (char*)malloc( sz );
    fread( buf, sz, 1, fp );
___

■ ftell

SYNTAX long ftell(FILE *FP); DESC File Pointer の位置を返す

    // FileSize をとる
    fseek(fp,  0, SEEK_END);
    uint32_t e = ftell(fp);


    printf("file pos = %ld\n", e );
    fseek(fp,  0, SEEK_SET);
    int s = ftell(fp);
    printf("file pos = %ld\n", s );
    

___

■ rand

SYNTAX int rand() DESC 0 - RAND_MAX の値を返す。 WARNING あまり random でないので利用しないこと。
    include< stdlib.h>
    int r = rand();
___

■ scanf

SYNTAX int scanf( const char *fmt, ... );
    // space, tab などの 空白文字は 無視される    
    // shell> 25 DEC 1111
    scanf( "%d %s %d", &day, month, %year );


  WARNING 
    // 値を格納できるように Pointer でないといけない
    BAD
      // 領域外の Memory にアクセスされてしまう
      int n;
      scanf( "%d", n );

    OK
      scanf( "%d", &n );
___

■ getchar

SYNTAX int getchar() DESC STDIN から 1文字の入力をうける WARNING int 型だが, 入力ストリームからうけるサイズは 1 byte #define getchar( ) getc(stdin)
___

■ gets

SYNTAX char *gets( char *buf ); DESC 標準入力から 改行コード \n があるまで buf へ読み取る。
___

■ fgets

SYNTAX char *fgets( char *buf, int n, FILE *fp ); DESC 行単位で file から n-1 サイズ分の文字列を buf へ読む。 読み込む文字は \n も含まれる。 最後に '\0' が追加される。 \n が途中できた場合, その時点で終了。 RET !0: 読み込んだ領域の先頭アドレス

    vector< string> readText( const char *path )
    {
      vector< string> a;

      char buf[1024];
      FILE *fp = fopen( path, "r" );

      while( fgets( buf, sizeof(buf), fp ) ) {

        // [\n] 削除
        buf[ strlen(buf) - 1 ] = '\0';
        a.push_back( buf );

      }

      fclose(fp);
      return a;
    }
標準入力も FILE *なので fgets から読むことができる。
  {
    char buf[1024];
    while( fgets( buf, sizeof(buf), stdin ) ) {
      // [\n] 削除
      buf[ strlen(buf) - 1 ] = '\0';
      printf( "stdin input  [%s]\n", buf );
    }
  }
指定したディレクトリ内のファイルをアーカイブする。
    find -name "*.bmp" | xargs cygpath -am |  ./archive.exe
___

■ putchar

SYNTAX int putchar(int c); RET DESC stdout へ 文字 c を 出力する #define putchar(c) __sputc(c, stdout) nm /lib/libc.a

    ./main

    # Pipe
    echo abcdef | ./main


    int main() {
      int c;

      // stdin から 1 文字取得 -> keyboard なら block される
      c = getchar();

      // stdout への Buffer を 0 にすると, すぐに出力される
#if 0
      setbuf( stdout, NULL );
#endif

      for (c = 'A'; c < = 'Z'; c++) {

        // Buffering されるため, すぐには画面には表示されない
         putchar(c);
      }

      sleep( 3 );

      // ここで出力
      printf("finish\n");
    }


___

■ putc

SYNTAX int putc(int CH, FILE *fp); DESC fp が指すストリームへ1文字を出力するマクロ。 CH が指すデータは int 型から unsigned char 型へ変換後に出力される。
___

■ puts

SYNTAX void puts(); DESC stdout へ指定文字列を出力するマクロ。
    fputs( str, stdout);  // == printf( str );
WARNING 実装によっては文字数制限あり. 360 ( 256 しか入力できない. )
___

■ math

    #include< math.h> 
    #include< stdlib.h> 
___

■ abs

SYNTAX int abs(int i); DESC i の絶対値をかえす
___

■ fabs

SYNTAX double fabs(double d); DESC d の絶対値をかえす
___

■ fabsf

SYNTAX float fabs(float f); DESC f の絶対値をかえす ANSI C 準拠ではないが、 VisualC++, gcc コンパイラでは使えそう。
    float f = -0.1f;
    f = fabsf( f );
    
    printf( "ret %f\n", f );
___

■ stdlib

    #include< stdlib.h> 
___

■ atoi

SYNTAX int atoi( const char *) DESC 文字列を 数値に変換
    int i;

    // 10
    i = atoi( "10" );

    // 10
    i = atoi( "10.1" );

    // 数値に変換できない場合は 0
    // RET
    //    0
    i = atoi( "aaa" );
___

■ abort

SYNTAX void abort() DESC プログラムを不正終了する。 C++ 例外の terminate() からも呼ばれる。
    abort();
___

■ getenv

DESC C 標準関数. 環境変数の値を取得 SYNTAX // const char * でない点に注意 char *p = getenv( ENV ); char *p = getenv( env ); // 大文字小文字 同じ結果 ? RET OK : ptr FAIL: NULL ENV は大文字で統一
___

■ qsort

SYNTAX void qsort( void *data, // 並び替えるデータのアドレス size_t nr, // 要素数 size_t size, // 各要素の size int(*compar)(const void *a, const void *b) // 比較関数 ); DESC nr 個の大きさ size の要素をもつ配列を並べ変える。 昇順に並べるには比較関数は次の規約に従うようにする。 比較関数 int(*compar)(const void *a, const void *b) a > b : return positive a < b : return negative a == b : return 0 WARNING 二つの要素の比較結果が等しいとき 並べ変えた後の二つの順序は規定されていない
    int cmp( const void *_a, const void *_b ) {
      int *a = (int *)_a;
      int *b = (int *)_b;

      if ( *a > *b ) return 1;
      else if ( *a <  *b ) return -1;

      return 0;
    }

    int a[] = { 1, 4, 9, 2, 5 };
    size_t nr = sizeof(a)/sizeof(int);

    // 1 2 4 5 9
    qsort( a, nr, sizeof(int), cmp );
___

■ bsearch

SYNTAX void *bsearch( const void *key, // 検索する値 const *void // 配列の先頭アドレス size_t nr, // 要素数 size_t size, // 要素ごとのサイズ int (*COMPAR)(const void *, const void *) ); DESC ソートすみの配列から、key と同じ値をもつ要素を検索してそのアドレスを返す。 比較関数 int(*compar)(const void *a, const void *b) a > b : return positive a < b : return negative a == b : return 0
    int cmp( const void *_a, const void *_b ) {
      int *a = (int *)_a;
      int *b = (int *)_b;

      if ( *a > *b ) return 1;
      else if ( *a <  *b ) return -1;

      return 0;
    }

    int a[] = { 1, 4, 9, 2, 5 };
    size_t nr = sizeof(a)/sizeof(int);

    // 1 2 4 5 9
    bsearch( 1, a, nr, sizeof(int), cmp );
___

■ ctype

  #include< ctype.h> 
___

■ isspace

SYNTAX int isspace( int c ); DESC c が空白文字の場合、0 以外の値を返す RET !0 : c が空白文字 (0x09 〜 0x0D || 0x20) POINT 結果は現在のロケールの LC_CTYPE カテゴリの設定によって異なる POINT CRT デバッグ ライブラリを使用すると CRT アサートを表示する CRT デバッグ ライブラリを使用すると isspace はパラメータを配列のインデックスとして使用し
___

■ ispunct

SYNTAX int ispunct( int c ); // Locale を指定する Version int _ispunct_l( int c, _locale_t locale ); DESC 文字が区切り文字かどうかを判定 RET !0 : c が特定の区切り文字の表現 POINT 区切り文字 とは 印字可能な文字 から 次の範囲ではないもの 印字可能な文字とは ( 空白文字 || isalnum(c) != 0 ) でない文字のこと
___

■ isalpha

SYNTAX int isalpha( int c ); DESC c が英字の表現の場合 これらの各ルーチンは 0 以外の値を返す RET !0 : c が A 〜 Z、|| a 〜 z
___

■ isalnum

SYNTAX int isalnum( int c ); DESC c が英数字のいずれかである場合、0 以外の値を返す c が isalpha || isdigit の値が 0 以外になる場合 ( c が A 〜 Z、a 〜 z、|| 0 〜 9 ) POINT isalnum の結果は 現在のロケールの LC_CTYPE カテゴリの設定によって異なる iswalnum はテスト条件の結果はロケールとは無関係 POINT UNICODE は Locale を統一しているということ
___

■ isleadbyte

SYNTAX int isleadbyte( int c ); RET !0 : テスト合格 0 : テスト不合格 "C" ロケール, シングルバイト文字セット (SBCS: single-byte character set) ロケールでは isleadbyte は常に 0 を返す
___

■ setlocale

SYNTAX char *setlocale( int category, // 設定する locale のカテゴリ const char *locale // Locale 名 ); wchar_t *_wsetlocale( int category, const wchar_t *locale ); DEP < locale.h> REF v=VS.71.aspx DESC RET NULL : 設定が無効 !NULL : 設定された Locale 名への Pointer
    // すべての Category を "english"
    setlocale( LC_ALL, "English" );

POINT Category の種類
  LC_CTYPE
    文字処理関数 (isdigit、isxdigit、mbstowcs、mbtowc の各関数は除く)。
POINT Localeとは 国や言語にあわせた環境設定のこと この地域性に合わせてプログラムのさまざまな側面をカスタマイズできる ロケールのカテゴリは 日付,通貨値の表示形式など 1 つの言語で複数の形式がサポートされている場合 その言語の既定文字列を locale に設定したときに setlocale 関数が戻す値をチェックし どの形式が有効になっているのか確認する必要がある たとえば、 "chinese" を指定すると chinese-simplified || chinese-traditional のいずれかの値が返る POINT 引数 locale は、ロケール名を指定する文字列へのポインタです locale で空の文字列を指すと そのロケールは実装で定義されているネイティブ環境になる
    setlocale( LC_CTYPE, "" );  // 自分の環境では 日本語 ( SJIS )の isleadbyte() が機能した
値 C は、C に関する ANSI 規格に最低限準拠した環境を指定します C ロケールでは char 型のデータがすべて 1 バイトで表現され 値が常に 256 未満と想定される C ロケールは、Microsoft Visual C++ Version 1.00、Microsoft C && C++ の旧バージョンでサポートされている唯一のロケールです Microsoft Visual C++ では、「言語および国/地域識別文字列」で示す すべてのロケールをサポートしています プログラムの起動時に 次のステートメントと同等の処理が実行される
    setlocale( LC_ALL, "C" );
___

■ math

___

■ atan

SYNTAX float atanf( float ) double atan ( double ) DESC tangent の値から [ -PI/2 : PI /2 ] の範囲の radian を返す
    float rad = atanf( v.z / v.x )
___

■ system

___

■ exit

SYNTAX void exit( int ) DESC プログラムを終了する。
___

■ atexit

DESC exit() の前にコールされるコールバックを指定する。 int atexit( void (*fn)() );
___

■ abort

SYNTAX void abort() DESC プログラムをを異常終了させる。 SIGABRT 例外を発生させる。
___

■ atof

SYNTAX double atof( const char *s ) DESC 文字列表現の数値を double 型に変換する。 POINT strtod( s, (char**)NULL )と同じ
___

■ system

SYNTAX int system( char *cmd ); RET シェルが返す終了コード。 DEP < stdlib.h> DESC Execute command string 別のコマンド(Program)を実行する OS の Shell( Windows なら cmd.exe )に引数の文字列をわたす こうしているのと同じ :: こういう呼び出しをすると Block される cmd> xxx.bat :: これは Block されない cmd> start xxx.bat 起動した Program が終了するまでまつ ( 正しくは cmd.exe が終了するまでまつ ) WARNING Windows Application から実行すると, ConsoleWindow が表示される。 こうすると とりあえず できる system( "start /min xxx.bat"); ProcessTree 的にはこうなる
    // ie. system()  は cmd.exe を起動する < -> cmd /c "xxx" と同じ
    xxx.exe
      cmd.exe // system()

start command を使うとこうなる

  // 親 Process が死ぬと ↓の状態になるらしい

  EXplorer.exe
    cmd.exe
      xxx.exe

  cmd.exe   // なぜかここにできる


  system( "start /min xxx.bat");

  // 死ぬ前はこう
  EXplorer.exe
    cmd.exe        // system(); から起動した cmd.exe
                    最初に一瞬見えるのは, すぐに この cmd.exe が終了するから
      cmd.exe      // start     から起動した cmd.exe


  // 親 cmd.exe が死ぬとここにくる
  cmd.exe

  // system("xxx") はコマンドライン引数なのでこうもかける
  system( "echo start && sleep 1 && echo bbb && sleep 2 && echo finish " );

  // path は POSIX でも問題ないらしい
  system( "d:/foo.bat" );

  WARNING
  system( "d:\foo.bat" );
  system( "d:\\foo.bat" );

POINT system() は OS の Shell( cmd.exe )を起動する system("xxx") は コマンドライン にコマンドを打つのと同じ
___

■ 非.ANSI C

___

■ sprintf_s

SYNTAX int sprintf_s( char *buffer, size_t sz, // バッファサイズ const char *format [, argument] ... ); RET -1 : 失敗 DESC VS2005 から 文字列操作関数の使用に警告がでる 文字数を指定するのは 責任はあなたにありますよ ! ということ sprintf_s は 出力バッファのサイズを受け取り、 バッファが小さすぎて出力テキストを格納できないなら バッファは空文字列に設定され無効なパラメータハンドラが呼ばれる。 snprintf とは異なり sprintf_s() は必ずバッファは null で終わる。 sprintf_s と sprintf の違い sprintf_s は書式指定文字列の有効な書式指定文字をチェックするが sprintf は書式指定文字列またはバッファが NULL ポインタかどうかのみをチェックする。 WARNING "test" < -> "test\0"と同じ 5 byte かきこまれる 4 文字だと思うと大怪我をする // 次はおちる // Debug では : Assert: Buf Too Small となる // Release では : おちる sprintf_s( buf, 1, "" ); 警告を消すには
    #define _CRT_SECURE_NO_DEPRECATE 1
    #pragma WARNING(disable:4996)

    #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
WARNING null terminate されないので _snprintf() は禁止 !
    {
      // Buffer Size = 8
      char buf[] = "1234567";

      int ret = _snprintf_s( buf, sizeof(buf), sizeof(buf)-1, "foo" );
      int ret = _snprintf_s( buf, sizeof(buf), _TRUNCATE, "foo" );

      assert( ret != -1, "fail" );


      if ( ret == -1 ) {
        printf( "切り捨てられた\n" );
      }
      else {
        printf( "%d + 1 文字かきこみました\n", ret );
      }
    }
___

■ _snprintf_s

SYNTAX int _snprintf_s( char *buf, // 書きこむバッファへのポインタ size_t szBuffer, // バッファサイズ size_t count, // 書く文字数 const char *format [, argument] ... ); RET -1 : バッファサイズが足りずに切り捨てられた N : 書いたバイト数 ( null を除く ) DESC 指定したバッファへ, count バイト数の文字 + NULL 文字を書き込む POINT Secure といっても 引数の指定を間違えるとおちる 意味は szBuffer の 大きさの Buffer へ カウント数 + [\0] バイトを書いてね ! という意味 だから 次のように言うと , 馬鹿正直に実行しておちる 適切な指示をしないと ダメということ
    {
      // 8 byte  の大きさ
      char buf[] = "01234567";

      // + null だけ overrun する
      // ERROR
      _snprintf_s( buf, sizeof( buf ), sizeof(buf), "01234567" );

_TRUNCATE( イッパイ まで ) を利用すれば, バッファオーバーランをしない
    // n = -1,  "0123456" 
    char buf[8];
    int n = _snprintf_s( buf, sizeof( buf ), _TRUNCATE, "01234567" );
以下のようにするのが正しい。null terminate してくれるのを忘れずに。
    _snprintf_s( buf, sizeof( buf ), sizeof(buf)-1, "abcdefgh" );
___

■ _popen._pclose

SYNTAX DESC System 関数に Pipe 機能を追加した内容 shell に Command を実行させて, Read, Write としての Pipe を取得する WARNING ConsoleWindow は表示されてしまう 表示しないためには

  int test() {


    FILE *in_pipe;

    // 読み込み用バッファ
    const int SZ = 256;
    char buf[SZ + 1];
    int nr;

    memset(buf,'\0',sizeof(buf));


    /* 
       POINT
          stdout から取得するには 読み込み用の PIPE を開く
          stdin へ書き込むには 書き込み用パイプを開く
    */

    // hostname の結果をうけとる
    in_pipe = _popen("hostname","r");

    /* 
      処理は通常のファイルストリームと同じ 
    */
    if(in_pipe != NULL){

      nr = fread(buf,sizeof(char),SZ,in_pipe);

      while ( nr > 0 ) {
        puts( buf );
        nr = fread(buf,sizeof(char),SZ,in_pipe);
      }


      /* 閉じる */
      _pclose(in_pipe);
      return 1;
    }

    return 0;
  }



___

■ sizeof

DESC object の memory 占有領域を調べる object の size なのでポインタを指定するとポインタオブジェクトのサイズを返す
     void func( char *buf ) {
        // ERROR: sizeof( buf ) == 4
        memset( buf, sizeof(buf), 0 );
     }
TIP COUNTOF macro で 宣言が可視の配列( pointer でない )のサイズを取得可能 count of では ptr 配列objsize / 1ptr 配列objsize として計算 WARNING wptr 配列では sizeof( ptr[0] ) = 4;
       int data[10];  // = 40
       int *p
       p = data;
       sizeof( p ) = 4   // pointer object size == 4
       sizeof( *p ) = 4  // p がさす obj という解釈にならない
___

■ unicode

lstrcpy( LPTSTR str1, LPCTSTR lpString2 )
___

■ 呼び出し規約





  DESC
    関数コールをするときにスタック上への引数の渡し方と、後方付けの方法をルール化したもの。

    複数の言語で呼び出し方が異なるため.
    関数呼び出し時の方法のこと。

  POINT
    
    
    よく使うものは次の3つ
     __cdecl    ( 呼ぶ側がスタックの方付けをする. C, C++ におけるデフォルトの規約 )
     __stdcall  ( 呼ばれた側がスタックの方付けをする. Win32 システム関数で採用されている ) 
     __this
呼び出し規約によって関数の修飾名も決まる。 呼び出し規約を変えると、 混合モードで表示されるアセンブラコードが代わることを確認できる。 デバッグ時にアセンブラコードをトレースする際に役にたつ。 call stack( stack ) への格納方法, 復帰方法, 名前修飾が異なる testcdecl( g_str, 1, 'a' );
    // 引数をスタックに push 
    push 61h
    push 1
    mov  eax, [g_str(0040000)]
    push
    
    // 関数をコール
    call testcdecl(0040000)

    // 後方付けは 呼ぶ側がする ( 12 byte スタックポインタを戻す ) 
    add esp, 0ch
___

■ cdecl

引数のセット順 右から左 関数名の修飾 _ がつく。( test() -> _test() ) スタック管理 呼び出し側がスタックを片つける intel86 系で使用される。 sensitive 戻り値は EAX に格納される。
    // 明示的に cdecl 規約で呼ぶことを宣言する。
    void _cdecl function( param );
___

■ stdcall

引数のセット順 左から右 関数名の修飾 _ と最後に @ と引数のバイト数をつける。( test() -> _test@4() ) スタック管理 呼ばれた側がスタックを片つける win32 API 標準. stack の掃除は sub func 自身でする( -> 可変長の引数 list は 未サポート ) POINT _XXX@N という関数名 N: 引数サイズ( ie. stack clean のサイズを通知 ) 引数をクリーンするためにサイズを知る必要があるということ
___

■ thiscall

引数のセット順 右から左 関数名の修飾 なし。 スタック管理 呼ぶ側がスタックを片つける _stdcall とほぼ同じ。 this ポインタは ecx に格納される。
___

■ firtstcall

register を利用して 引数渡しをする -> ということは, register は早い 戻り値は register, stack にはいる @XXX@N POINT
    呼び出し規約により, Symbol に変更が加えられる ( 数値は arg size )
    arg

    cdecl
    stdcall    : _ + (関数名) + @8
    fastcall   : @ + (関数名) + @8
___

■ C99(Cの新機能)




___

■ stdint

    #include < stdint.h>
 C 言語のプログラムを移植するときの問題点の一つに、 typedef された int 型の大きさがあります。 例えば、 int型 が 32bit と仮定して、int32 という型を typedef して作ったとします。 そしてソースプログラム中で int32 という型を使用します。 しかし 他の環境へそのソースプログラムを持っていった時には int が 32bit でないかもしれません。 したがって、もしそのままソースプログラムを使用すると 32bit を仮定しているプログラムなのに、実際は 16bit になってしまったということが起こり得ます。 そのようなことから環境が変わった場合、 新たに定義し直す必要があります。stdint.h はこの問題の一つの解決方法を提示します。  整数を、厳密、最小、演算が速い最小、ポインタ格納可能、最も大きな幅、というクラスにわけ、それをみたす型と限界を定義します。だから、例えば、演算が速い最小の整数型を使えば、他の環境へ持っていってもそのままソースプログラムを再利用することができる可能性が高くなるわけです。 intN_t 符号付き整数型の typedef 名 uintN_t 符号なし整数型の typedef 名 厳密にその幅を持つ整数型。 これらの型は任意であるが、もし実装が 8, 16, 32, 64 ビットの整数型を提供しているなら相当する typedef 名を定義する必要がある。 例:N=32の場合:int32_t, uint32_t ポインタを格納可能な整数型に関する 定義定義名 説明 intptr_t ポインタを格納するのに適切な符号付き整数型の typedef 名 uintptr_t ポインタを格納するのに適切な符号なし整数型の typedef 名 void* を (u)intptr_t に変換でき、かつそれを void* に戻せ、 その結果が元のポインタと等しくできる整数型。これらの型は任意である。 WARNING C99 に準拠していない VisualStudio 2008 では存在しない。 VisualStudio 2010 では $VC/VC/include/ 以下に存在する。 複数の環境で利用するには以下のようにする。
    // VisualStudio 環境では __int32 の別名として int32_t を定義する
    #ifdef __MSC_VER
    typedef __int32  int32_t
    #else
    # include< stdint.h> 
    #endif
___

■ 高速化


___

■ キャッシュメモリ(CacheMemory)

cache とは隠し場所のこと メインメモリからデータを CPU ( レジスタ )にメモリを転送した際に そのデータを CPU に近いメモリにためておくこと。 こうすると次に必要になったデータを近い場所からとることができる。 L2, L3 キャッシュという。 メモリから読む時は 64 byte 単位などをまとめて読むので なるべく連続したアドレスでアクセスすると キャッシュ( 近い場所 )からデータをとれる。 キャッシュを有効に使うために次のことに気をつける。
     データのサイズを小さくする。 int ではなく short にする
     一緒に使うものをまとめておく。 ( new を利用しない )
    const unsigned int n = 1024*1024*16;
    const unsigned int N = 10*10;
    static int a[n];

    static __int64 a[n];
    
    memset( a, 0, sizeof(a) );

    for( unsigned int i=0; i< n; i++ ){
      for( unsigned int j=0; j< N; j++ ){
        ++a[i];
      } 
    } 
___

■ Endian(エンディアン)


    数値の桁がどういう順番で並んでいるか
    ByteData [0x0000000]を上位からか、下位からかどちらかの方法でメモリに格納する順番
    MultiByte にならないと問題にならない

    1バイトより大きいサイズのオブジェクトの表現方法は環境によって異なる。

    LittleEndian :
      ちっちゃい順
    int i = 0xAABBCCDD;
    
    // メモリ上では 下の桁から格納される
    [DD][CC][BB][AA]
ネットワーク経由で送られたデータはビッグエンディアン

    // メモリレイアウト
    [11][22][33][44]

    // BigEndian としてみると
    0x11223344

    // LittleEndian としてみると
    0x44332211

BigEndian : 大きい桁順 ( PowerPC, ネットワークバイトオーダー ) LittleEndian : 小さい桁順 ( インテル系PC )
    Big endian( 人間にとってわかりやすい )
       

    上位バイトからそのまま 
    [11][AB][22][CD]
ファイルに格納する byte 列も当然影響をうける PC 環境では BE はありえない Endian が異なる環境では、バイトの並びを並び替える。
    uint32_t tmp = 0;

    tmp |=   0x000000ff & (ret >> 24);
    tmp |= ((0x000000ff & (ret >> 16)) < <  8);
    tmp |= ((0x000000ff & (ret >>  8)) < <  16);
    tmp |= ((0x000000ff & (ret >>  0)) < <  24);  // 下位 を 上位へ

    ret = tmp;
    
    uint16_t tmp;
    tmp |=   0x00ff & (ret >> 8);
    tmp |= ((0x00ff) & (ret >> 0)) < <  8;

環境によらず Endian をそろえるには int 型のオブジェクトがきたら必ず 下位の桁から順番にストリームへ出力する。
    char str[4];

    str[0] = ( i & 0x000000ff );
    str[1] = ( i & 0x0000ff00 ) >> 8;
    str[2] = ( i & 0x00ff0000 ) >> 16;
    str[3] = ( i & 0xff000000 ) >> 24;

    ofstream out;
    out.write( str, 4 );
POINT endian の相違は単一のシステム( 閉じた世界 )で運用する場合は問題なし。 WARNING 異なるシステムでネットワークを通して、[ バイト単位 ]のやりとりをする場合 2. 異なるシステム間でバイナリファイルを交換する場合。 3. 異なるシステムにプログラムを移植する場合。 4. 構成するプロセッサが異なるマルチプロセッサ環境で共有メモリを使用する場合。
    {
      unsigned long x = 0x11223344UL;

      unsigned char *p = (unsigned char)&x;

      // Memory 内の表現を見る
      for( i=0; i< sizeof(long); i++ ){
        printf( "%x", *p++ );
      }

    }

    // これと同じ
    fwrite( &x, sizeof(x), 1, stdout );


___

■ NetworkByteOrder

TCP/IP network ではendian の差分を統一するため、 多バイトからなるパケットをBig endian で統一。 画像、音声ファイルのバイナリファイルも互換性を保つため、endian を規定。 Unicode は構成単位が2byte。バイトオーダーマーク( BOM )というもので エンディアン方式を判別する仕組み。
___

■ 再帰処理


    同じ構造がネスト化されている状態では、再帰処理ができることが多い。

    たとえばツリー構造は、ツリーのある部分もツリーであるので
    再帰処理ができる。

    再帰処理は基本的に処理が簡単になる。

    
___

■ データ構造


    
___

■ 配列

ソートされた配列は 2分探索が使えるようになる。 この場合は計算量が O(logN) にまで減る。
___

■ リンクリスト

___

■ バイナリーツリー

2分木は検索を高速をすることができる構造。 データの集合を自分より大きい、小さいで分別してしまうことで 検索対象を半分くらいに減らすことで高速化できる。
















NINJAIDX 16