Flexible Faith

記憶力を頼りに今までやってきたけどもう限界だ…!
備忘録を書くぞーッ!

2015年06月

閏秒について

閏年についてはご存知の方が多いと思います。
2月の日数が28→29日、1年が366日になる年で、
4の倍数の年は閏年、
でも100の倍数の年は閏年じゃない、
しかし400の倍数の年は閏年というめんどくさいアレですが、
閏秒なんてものもあるようで。

2015年の7月1日の午前9時(JST)直前、08:59:60という時間が1秒間挿し込まれるとのこと。
秒の値が0~59であることを期待しているプログラムは不具合を起こす可能性があるということです。
数年に一度は閏秒による調整が発動するようなので、時刻を扱う場合は意識しておいた方がよさそうですね。 

イテレータからポインタへの変換


// テストクラス
class Test
{
public:
int id;
};

// テストのvector
vector<Test> testVector;

// idからTestクラスのポインタを得る
Test* GetTestByID(int id)
{
for(vector<Test>::iterator it = testVector.begin(); it != testVector.end(); ++it ){
if( (*it).id == id ){

return &*it; // itをそのまま返すとコンパイルエラーになる場合があるので…
}
}

return NULL;

thisにmemsetしてメンバ変数をゼロクリアしてもいいの?

職場でメンバ変数の初期化を忘れてはCoverityによく叱られておりますが、
コンストラクタでthisにmemsetすれば解決なのでは?
↓のような感じで…

class foo{
int a;
int b;
foo()
{
memset(this, 0, sizeof( *this ) );
}
};  

…と思ったものの、 これは動作保障されないようです。

<参考>
[迷信] コンストラクタで自身をゼロクリア

地道に1つ1つメンバ変数を初期化するのが安全で確実ですね。 

64ビットフラグを扱うときは64ビット整数値をビットシフトする

セーブデータを64ビットフラグで管理しようとした時に、
何の気なしに↓のようなことをしていたら、どうも後半のビットがうまく操作できていない…。

unsigned long long savedata;

// セーブデータにフラグをセット
void SetFlag(int bitNo, bool flag)
{
unsigned long long mask = ~(1 << bitNo);
unsigned long long add = (flag ? 1 : 0) << bitNo;

savedata &= mask;
savedata |= add; 



問題はビットシフト対象の1という整数がint型として扱われているため、32ビットしかないこと。
なので、32ビットを越える部分は…ちゃんと調べてませんが、たぶん全てのビットが0なのかな。
とにかくおかしくなるので直します。


// セーブデータにフラグをセット(改)
void SetFlag(int bitNo, bool flag)
{
unsigned long long one = 1; 
unsigned long long mask = ~(one  << bitNo);
unsigned long long add = (flag ? one  : 0) << bitNo; // (0は…まあいいか)

savedata &= mask;
savedata |= add; 
}  


C++のキャスト

同じ型を変換する場合でも、
色んなキャストを駆使して巧みに惑わせてくるコードに職場で出くわしたので、
一通り調べてみた結果、ざっくり以下の理解を得ました。

  • dynamic_cast 
継承関係がある型変換で使う。失敗するとNULLを返す
  • static_cast
暗黙的変換ができる場合にはこれを使う。ほんとに?
  • const_cast
constを外す。こういうのもあるのか……役割が明確で助かります。
  • reinterpret_cast
とにかく強制的にキャストしたい場合に使う。



色々調べてみると奥が深いですね。
特にstatic_cast。

http://www.geocities.jp/bleis_tift/cpp/newcast.html
「具体的には、暗黙的な変換が存在する場合にコンパイルが成功し、 キャストが不正な(キャストできない)場合はコンパイルエラーとなります。」

https://msdn.microsoft.com/ja-jp/library/cc440191(v=vs.71).aspx
static_cast を使えば、言語仕様では暗黙の変換が許されない場合でも明示的な変換が可能です」


?????

型変換したいだけなのに、なんでこんな難しいことを調べないといけないんだ…!
よくわからんので、ひとまず動けば良しとしよう…。


ただし、聞くところによるとreinterpret_castは余計なチェックをしないため動作が速いらしいです。
どのくらい速いかは不明。今夏ベンチマーク予定。
逆にdynamic_castとかしてても、そのあとNULLチェックしていないとあんまり意味がなさそう。 


カテゴリー
  • ライブドアブログ