MW211 EXIT

devlog
C++/最小値最大値の定数
2012年07月27日
「limits.h」とか。。。
┌────┬┬───────────┬┬───────────┐
│   型   ││        signed        ││       unsigned       │
├────┼┼─────┬─────┼┼─────┬─────┤
│int     ││INT_MIN   │INT_MAX   ││          │UINT_MAX  │
├────┼┼─────┼─────┼┼─────┼─────┤
│int32_t ││_I32_MIN  │_I32_MAX  ││          │          │
│        ││INT32_MIN │INT32_MAX ││          │UINT32_MAX│
├────┼┼─────┼─────┼┼─────┼─────┤
│int64_t ││_I64_MIN  │_I64_MAX  ││          │          │
│        ││INT64_MIN │INT64_MAX ││          │UINT64_MAX│
├────┼┼─────┼─────┼┼─────┼─────┤
│char    ││SCHAR_MIN │SCHAR_MAX ││          │UCHAR_MAX │
│        ││          │          ││CHAR_MIN  │CHAR_MAX  │
├────┼┼─────┼─────┼┼─────┼─────┤
│short   ││SHRT_MIN  │SHRT_MAX  ││          │USHRT_MAX │
├────┼┼─────┼─────┼┼─────┼─────┤
│long    ││LONG_MIN  │LONG_MAX  ││          │ULONG_MAX │
└────┴┴─────┴─────┴┴─────┴─────┘
他にもいろいろあるよね。。。
分類:C/C++
C++/deleteしてもポインタはNULLにならない
2012年07月26日
先日、delete時にそのポインタがNULLか否かを一々確認する必要はなく
無条件に実行すりゃNULLの場合は無視してくれるということに触れた。

ただ、注意しなければならないのは、deleteしたらポインタを
自動ではNULLしてくれないということ。
手動で必ずNULLしよう。
┌──────────────────────────────────────┐
│delete p;                                                                   │
│p = NULL;                                                                   │
└──────────────────────────────────────┘

deleteしても元のアドレスを指したままになっている。
もちろんその先はありませんから大変です。
┌──────────────────────────────────────┐
│delete p;                                                                   │
│delete p;                                                                   │
└──────────────────────────────────────┘
こうすると、例外になる。

┌──────────────────────────────────────┐
│delete p;                                                                   │
│p = NULL;                                                                   │
│delete p;                                                                   │
└──────────────────────────────────────┘
これならOK。

ま、直線的にこんな書き方はしないけど、いろいろ処理がつながると
結果的にこんなことになりかねない。
分類:C/C++
C++/delete時のNULL以外確認はいらない
2012年07月25日
┌──────────────────────────────────────┐
│if (p != NULL) {                                                            │
│    delete p;                                                               │
│    p = NULL;                                                               │
│}                                                                           │
└──────────────────────────────────────┘
みたいに、念のためポインタがNULLじゃないことを確認してから
領域を解放(delete)する処理を見かけるが、
本来は「delete NULL;」でもスルーされる(処理が起こらない)というC++の規約があり
このif文は冗長なようだ。

これだけでよい。
┌──────────────────────────────────────┐
│delete p;                                                                   │
│p = NULL;                                                                   │
└──────────────────────────────────────┘

なんか、ちょっと不安だけど。。。
分類:C/C++
C++/オブジェクト指向との相違点
2012年07月23日
C++でオブジェクト指向に従って設計すると、
以下の不都合(というのはあくまでC++目線で)がある。

オブジェクト指向的な考え方
(1) そのインスタンス固有の情報は生成時に確定させる
    コンストラクタから値を引き渡すなど
    ・固有情報不明(未確定)のインスタンスはおかしい
(2) あらかじめ決まった前処理はコンストラクタの時点でやってしまう
    ・前処理のやり忘れを防げる

C++の事情
(1) メモリリーク対策としてできるだけヒープ領域より
    スタック領域でインスタンスを生成した方が有利
    ・メモリ解放漏れの疑念が減る(これはメモリリーク発生時効果絶大)
    ・但し、スタック領域にインスタンスを生成する場合、
      コンストラクタの実行タイミングに不自由が生じる
      (固有情報未確定時にインスタンス生成しなけらばならない)
      よって、別途コンストラクタ同等メソッド(初期処理メソッドなど)を用意し
      それを必ず実行するルールとする(しかしながら実行漏れのリスクあり)
(2) コンストラクタ中で例外が発生した場合メモリリークする恐れがある
    また、それを隈なく対処するとなると結構労力を費やす
    ・コンストラクタでは値初期化ぐらいの軽い処理にとどめてしまうルールとする
    ・前処理にあたるものは別途メソッド(初期処理メソッドなど)を用意し
      こちらで行う(しかしながら実行漏れのリスクあり)

本来のオブジェクト指向を追求すると(美しい形で)実行漏れがなくなるが、
C++としてはメモリリークのリスクが高まるので
多少いびつでも、メモリリーク防止に努めた方がよい
#実行漏れといっても初期処理は最初の決まった位置に置けばよいだけ
  一方メモリリーク防止の解放処理は様々なルートを考慮しなければならないから
  コスト面(チェック箇所)では格段に違う
分類:C/C++
C/C++/最後のカンマ
2012年07月21日
JSONでは最後に余計なカンマをつけると怒られてしまうが、
C/C++の場合は以下の通りらしい。
┌──────┬─────────┬──────────┬──────────┐
│            │                  │         ○         │         ×         │
├──────┼─────────┼──────────┼──────────┤
│配列初期化子│int  a = {1,2,3,};│C90、C99            │                    │
│            │                  │C++98、C++03、C++11 │                    │
├──────┼─────────┼──────────┼──────────┤
│列挙子      │enum a = {1,2,3,};│C99                 │C90                 │
│            │                  │C++11(C++0x)        │C++98、C++03        │
└──────┴─────────┴──────────┴──────────┘
enumの場合の最後のカンマは、C++03では正式には不正だったが、
あまり気づかなかったらしい(コンパイルで許容されてた?)
分類:C/C++
C/C++/配列数の取得
2012年07月20日
┌──────────────────────────────────────┐
│count($array);                                                              │
└──────────────────────────────────────┘
PHPだと配列$arrayの配列数を求めるのに、count()が使える。

では、C/C++では?

そんな便利な関数はありません。

ってな訳で、以下のようなマクロで代用しましょう。
┌──────────────────────────────────────┐
│#define count(array)  (sizeof(array) / sizeof(array[0]))                    │
└──────────────────────────────────────┘
分類:C/C++
VC++/CArrayについて
2012年07月13日
┌──────────────────────────────────────┐
│CArray a;                                                                   │
└──────────────────────────────────────┘
CArrayにて、以下は同じ。(三番目の項目をみている)
┌──────────────────────────────────────┐
│a[3]                                                                        │
├──────────────────────────────────────┤
│a.GetAt(3)                                                                  │
└──────────────────────────────────────┘
分類:C/C++
C言語/グローバル変数の定義
2012年07月12日
以下の組み合わせなら、OK。
┌──┬───────────────────────────────────┐
│a.h │int z;                                                                │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
├──┼───────────────────────────────────┤
│b.h │int z;                                                                │
├──┼───────────────────────────────────┤
│b.c │#include "b.h";                                                       │
└──┴───────────────────────────────────┘

以下の組み合わせだと、二重定義でNG。
┌──┬───────────────────────────────────┐
│a.h │int z;                                                                │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
│    │#include "b.h";                                                       │
├──┼───────────────────────────────────┤
│b.h │int z;                                                                │
└──┴───────────────────────────────────┘

以下も、二重定義でNG。
┌──┬───────────────────────────────────┐
│a.h │int z;                                                                │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
│    │#include "b.h";                                                       │
├──┼───────────────────────────────────┤
│b.h │#include "a.h";                                                       │
└──┴───────────────────────────────────┘

以下ならOK。
┌──┬───────────────────────────────────┐
│a.h │int z;                                                                │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
│    │#include "b.h";                                                       │
├──┼───────────────────────────────────┤
│b.h │extern int z;                                                         │
└──┴───────────────────────────────────┘

以下だと、実体がなくなってしまうのでNG。
┌──┬───────────────────────────────────┐
│a.h │extern int z;                                                         │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
│    │#include "b.h";                                                       │
├──┼───────────────────────────────────┤
│b.h │#include "a.h";                                                       │
└──┴───────────────────────────────────┘

以下とかもありがちなのか?
┌──┬───────────────────────────────────┐
│a.h │                                                                      │
├──┼───────────────────────────────────┤
│a.c │#include "a.h";                                                       │
│    │int z;                                                                │
├──┼───────────────────────────────────┤
│b.h │extern int z;                                                         │
├──┼───────────────────────────────────┤
│b.c │#include "a.h";                                                       │
│    │#include "b.h";                                                       │
└──┴───────────────────────────────────┘

よくわからん。そのうちちゃんと整理します。(上記はあまり信用しないでね)
分類:C/C++
C++/【未解決】書式付文字列結合
2012年07月11日
PHPだと書式に変換した文字列を結合するのはたやすい。
┌──────────────────────────────────────┐
│$a  = 'Kato';                                                               │
│$a .= sprintf('%d', 123);                                                   │
│$a .= sprintf('%d', 9);                                                     │
├──────────────────────────────────────┤
│echo $a;                                                        →'Kato1239'│
└──────────────────────────────────────┘

だからついCでも「sprintf()」の戻り値は編集後の文字列だと錯覚してしまうが
戻り値は処理結果(成功したか)であって、「sprintf(a, '%d', 123)」みたいに
編集後の文字列を取得する変数は、第一引数にねじ込まなければならない。

さて、MFC(Visual C++)において、CString型でFormatというメソッドがあるが
上記を再現すると、以下のようになってしまい、二倍の行を費やしてしまう
┌──────────────────────────────────────┐
│CString a, b;                                                               │
│a = 'Kato'                                                                  │
│b.Format("%d", 123);                                                        │
│a += b;                                                                     │
│b.Format("%d", 9);                                                          │
│a += b;                                                                     │
└──────────────────────────────────────┘

例えば、以下のようにすると、編集後のbが代入されるのではなく
bを編集した結果(成功したか)が代入されるみたい。
┌──────────────────────────────────────┐
│a += b.Format("%d", 123);                                                   │
└──────────────────────────────────────┘

また、こんな風に自己循環させるのもダメらしい。
┌──────────────────────────────────────┐
│a.Format("%s%d", a, 123);                                                   │
└──────────────────────────────────────┘

なんか、一行で書けるうまいてはないものか?(やっぱりユーザ関数?)
分類:C/C++、【未解決】
C++/静的メンバ変数の使い方
2012年07月10日
例えば、設定ファイルに決まった設定値があって、
一度読んでしまえば後はずっと同じで、それをクラスで共通的に使う場合。

こいつをクラス生成時のコンストラクタの引数に代入して使ったりする。

でも、毎回毎回クラスを生成するたんびにコンストラクタに代入するのもちょっと。

そんな時には静的なメンバ変数を使ってしまおう…って、それでいいのか?

でも、使う使わないは別として、使い方は知っておきたい。

以下の通りのようだ。

(1) クラスのメンバ変数を静的なパブリック属性として定義する。
┌──────────────────────────────────────┐
│class クラス                                                                │
│{                                                                           │
│public:                                                                     │
│    int32_t  メンバ変数;                                                    │
│}                                                                           │
└──────────────────────────────────────┘

(2) このクラスを使う側のクラスのグローバル領域で、同じ型で宣言する。
┌──────────────────────────────────────┐
│int32_t  クラス::メンバ変数;                                                │
└──────────────────────────────────────┘

(3) クラスを生成する前に値を代入する。
┌──────────────────────────────────────┐
│クラス::メンバ変数 = 値が決定した変数;                                      │
│while () {                                                                  │
│    ポインタ = new クラス();                                                │
│    delete ポインタ;                                                        │
│}                                                                           │
└──────────────────────────────────────┘
分類:C/C++
前へ 1 2 3 4 5 6 7 8 9 次へ