SlideShare une entreprise Scribd logo
1  sur  32
Télécharger pour lire hors ligne
組み込みでこそ
C++を使う100の理由
Aiming 大阪社内勉強会
2012-06-11 @kikairoya
喋ること
•   C滅びろ
•   C滅びろ
•   C滅びろ
•   C滅びろ
•   C滅びろ
「Cを使う必然性」の幻想
•   C++使うと遅くなるしCでいいよ
•   …同じならCでよくね?
•   いや例外とかでかいじゃん
•   templateとかよくわかんないし
C++使うと遅くなるしCでいいよ
• そうでもない
• 同じことを実現しようとすれば、ほぼ正確に同じだけ
  の命令数が必要
   – Cで書いてもC++で書いても生成コードサイズは
     大して変わらない(RTTIと例外テーブルは除く)
• 20年前の昔なら兎も角、21世紀も10年過ぎた現在
  ではJavaですらCより速い場合がある
「C++遅い」の主要因
• 無意味な仮想関数
   – dynamic polymorphismを使わないなら要らない
• newの乱発
   – Cと同じように単にスタックに配置すればいい
• SjLj例外ハンドリング
   – Dw2例外ハンドリングを使うか、OFFにする
おまけ:Javaのパフォーマンス
• http://blog.cfelde.com/2010/06/c-vs-java-
  performance/ とか
     g++ 4.3
        vs
  Sun Java HotSpot VM, version 1.6.0_20
…同じならCでよくね?
• んなこたない
• C++でしか出来ないことはあるけれど、Cでしか出来
  ないことはほとんど無い
   – C99の複合リテラル・名前付き初期化くらい
   – どちらもC++で似たような機能は実現可能
   – C89に限定すれば事実上「全く」無いと言える
いや例外とかでかいじゃん
• そげなことない
• 不要ならOFFにすればいいだけ
• RTTIも同様
• 例外飛ばしてたらリアルタイム性守れない場
  合があるので、その場合はOFF
• 例外無くてもデストラクタは正しく走るので、リ
  ソース管理も安全安心
templateとかよくわかんないし
• 面倒な部分はライブラリ側に全部隠せます
• エラーコードは確かに量多いですが…
  実行時に不思議な挙動をするか
  コンパイル時に説教されるか
  どっちがいいですか?
• コンパイル通した時点でデバッグ終了が理想
  – 現実は厳しいけれど、コンパイラが見つけ
    てくれるエラーの量はCとは段違い
便利で危険なprintf
• printfって便利だけど危ないよね…
• sizeof(int)==2の環境だと特に問題が顕在化
  しやすい
• それC++なら型安全に出来るよ
• ntfmtとか
• cprintfとか
printfの罠
• たとえばこんなコード

extern int g_value_for_something;

void logger() {
  printf("value:%d¥n",
   g_value_for_something);
}
printfの罠
• 「intが16ビットですぐ溢れるからlongにしよう」

extern long g_value_for_something;

void logger() {
  printf("value:%d¥n",
   g_value_for_something);
}
printfの罠
• 「intが16ビットですぐ溢れるからlongにしよう」

extern long g_value_for_something;

void logger() {
        !!!フォーマット指定子を変え忘れた!!!
  printf("value:%d¥n",
   g_value_for_something);
}
constexprなprintfなら
• 変え忘れたらコンパイルエラーにできます
extern long g_value_for_something;

void logger() {
  cprintf("value:%d¥n",
   g_value_for_something);
}
   FORMAT_ERROR_format_specifier_d_takes_int_but_
   given<T>::fail() [with T = long int]
void *パレード
• Cで汎用コンテナやアルゴリズム作ろうとする
  と、void *の山になりますよね…
• ライブラリで閉じていればまだいいけど、ユー
  ザコードでvoid *からキャストする必要がある
• それC++なら型安全に出来るよ
• STLとか
ビットフィールドの恐怖
• 組み込みでも一番低いレイヤではハードウェ
  アレジスタを叩く必要がある
• Cだとよくビットフィールド使うけれど…
• GCCでは間違ったアドレスにアクセスすること
  がある!
ビットフィールドの恐怖
• こんなありふれたコードから…

volatile struct {
      volatile unsigned int a: 8;
      volatile unsigned int b: 4;
} bitfield;

int main() {
   bitfield.a = 1;
}
ビットフィールドの恐怖
• こんな恐ろしいコードが!!!



  movl   $1, bitfield+3(%rip)
  ↑ (bitfield+3)番地に32ビットで書き込み
ビットフィールドの恐怖
• 組み込みでも一番低いレイヤではハードウェアレジ
  スタを叩く必要がある
• Cだとよくビットフィールド使うけれど…
• GCCでは間違ったアドレスにアクセスすることがあ
  る!(注: BTSにパッチ投稿済)
  – ベンダコンパイラでもコンパイルオプション一つで
    ビットオーダーが変わることがある
• それC++なら安全でポータブルに出来るよ
ビットフィールドの克服
• こんなコードを用意しておけば…

struct addr_t { size_t addr; };
template <typename T, int H, int L = H>
struct ioaccess_bit {
 template <int = bitsizeof(H)-1, int = H>
 struct gen_mask {
  static constexpr T value = (~static_cast<T>(0)<<H+1) ^ (~static_cast<T>(0)<<L);
 };
 template <int h>
 struct gen_mask<h, h> { static constexpr T value = ~(~static_cast<T>(0) << L); };
 constexpr ioaccess_bit(addr_t addr): addr(addr.addr) { }
 size_t addr;
// continue
ビットフィールドの克服
• こんなコードを用意しておけば…

// continued
 size_t addr;
 static constexpr T mask = gen_mask<>::value;
 constexpr T omit_bits(T x) { return x & ~mask; }
 constexpr T extract_bits(T x) { return (x & mask) >> L; }
 constexpr T shift_bits(T x) { return (x << L) & mask; }
 volatile T *get_addr() const { return reinterpret_cast<volatile T *>(addr); }
 operator T() const { return extract_bits(*get_addr()); }
 ioaccess_bit operator =(T v) const {
     T tmp = *get_addr(); *get_addr() = omit_bits(tmp) | shift_bits(v); return *this;
 }
};
ビットフィールドの克服
• こんな定義で…
struct { struct reg_t { struct can_mb_id_t {
   struct bit_t {
    static constexpr size_t base = 0x00090200;
    size_t offset;

        ioaccess_bit<uint32_t, 31> IDE = addr_t{base+offset};
        ioaccess_bit<uint32_t, 30> RTR = addr_t{base+offset};
        ioaccess_bit<uint32_t, 28, 18> SID = addr_t{base+offset};
        ioaccess_bit<uint32_t, 17, 0> EID = addr_t{base+offset};
    bit_t(size_t off): offset(off) { }
   } BIT;
 } ID; };
 reg_t operator[] (size_t n) { return reg_t{{{n}}}; }
} MB;
ビットフィールドの克服
• こんなコードが書けます。

int n = MB[0].ID.BIT.SID;
MB[0].ID.BIT.EID = 12;
assert(MB[1].ID.BIT.IDE == 1);
割り込みマスク
•   割り込みを一時的にマスクしたいこと、有りますよね
•   sti()/cli()でいいんだけど、もしネストされてたら…?
•   というかcli()とか呼ぶの忘れますよね
•   それC++なら自動化できるよ
単純な例
struct lock_interrupt {
  lock_interrupt() : masked(get_imask_ccr()) {
    set_imask_ccr(1);
  }
  ~lock_interrupt() {
    set_imask_ccr(masked);
  }
  bool masked;
};

// in some function...
  lock_interrupt lk;
  // do critical action, let's forget unmask interrupt flag!
}
醜い固定小数点演算
• Cで実数演算する場合は…
   – double/floatを使う
   – 整数を自前でシフトして使う
   – 固定小数点演算ライブラリを作る
• 固定小数点を使う場合、演算子使えなくて大変です
  よね…
• それC++ならスマートに出来るよ
美しい固定小数点演算
fixed calc_1(             void calc_1(
  fixed v,                 fixed *result,
  fixed u                  fixed *pv,
){                         fixed *pu
  v *= 1.5f;              ){
  return v + calc_2(u);    fixed tmp;
}                          fixed_from_float(&tmp, 1.5f);
                           fixed_mul(pv, pu, &tmp);
                              calc_2(&tmp, pu);
                              fixed_plus(result, pv, &tmp);
                          }
美しい固定小数点演算
• 演算子オーバーロードは用法・容量を守って
  正しく使いましょう。
まずは簡単なところから
• たとえC++の機能を使っていなくても、拡張子は.cpp
  にしましょう
• マクロで定数やインライン関数を書くのはやめて、
  static constやinlineを使いましょう
• テンプレートを「書く」のは慣れてからで十分
• 千里の道も一歩から
  C++マスターもBetter Cから
おしまい
• Let's C++!!!

Contenu connexe

Tendances

unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときShintarou Okada
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14Ryo Suzuki
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと信之 岩永
 
TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?Mr. Vengineer
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpsonickun
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装MITSUNARI Shigeo
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜UnityTechnologiesJapan002
 
並列化による高速化
並列化による高速化 並列化による高速化
並列化による高速化 sakura-mike
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロdigitalghost
 

Tendances (20)

Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるとき
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
llvm入門
llvm入門llvm入門
llvm入門
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?TensorFlow XLAは、 中で何をやっているのか?
TensorFlow XLAは、 中で何をやっているのか?
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装高速な倍精度指数関数expの実装
高速な倍精度指数関数expの実装
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
Lockfree Queue
Lockfree QueueLockfree Queue
Lockfree Queue
 
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜
C#×LLVM=アセンブラ!? 〜詳説・Burstコンパイラー〜
 
並列化による高速化
並列化による高速化 並列化による高速化
並列化による高速化
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 

Similaire à 組み込みでこそC++を使う10の理由

競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会7shi
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編道化師 堂華
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編egtra
 
Brief introduction of Boost.ICL
Brief introduction of Boost.ICLBrief introduction of Boost.ICL
Brief introduction of Boost.ICLyak1ex
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competitionyak1ex
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALegtra
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語るAkira Takahashi
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61TATSUYA HAYAMIZU
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門伸男 伊藤
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいdigitalghost
 

Similaire à 組み込みでこそC++を使う10の理由 (20)

競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会
 
C++0x総復習
C++0x総復習C++0x総復習
C++0x総復習
 
C++ tips4 cv修飾編
C++ tips4 cv修飾編C++ tips4 cv修飾編
C++ tips4 cv修飾編
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編
 
C++11概要 ライブラリ編
C++11概要 ライブラリ編C++11概要 ライブラリ編
C++11概要 ライブラリ編
 
Brief introduction of Boost.ICL
Brief introduction of Boost.ICLBrief introduction of Boost.ICL
Brief introduction of Boost.ICL
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Hupc 1
Hupc 1Hupc 1
Hupc 1
 
C++0x 言語の未来を語る
C++0x 言語の未来を語るC++0x 言語の未来を語る
C++0x 言語の未来を語る
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
C++11のつかいかた
C++11のつかいかたC++11のつかいかた
C++11のつかいかた
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 

組み込みでこそC++を使う10の理由