SlideShare a Scribd company logo
1 of 80
Download to read offline
2013年2月3日
第2回勉強会:スライド


              1
こっうた~ん♪


          2
はーい!




       3
koturn 0;の発表~




はっじまーるよ~♪       4
まずは、自己紹介から

       名前:koturn 0;

  趣味:数学、プログラミング

       エディタ:vim派

 言語:C/C++/C#/Java/Python
/Ruby/Javascipt/common LISP
       /elisp/Vim script

                              5
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                6
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                7
自作コンパイラ
            概要
●   プログラミング言語を作ろうという試みです
●   実用的になるように、Javaのクラスファイル
    (.class)を出力するようにしています




                             8
自作コンパイラ
      なぜJVMをターゲットに?
●   実マシン(レジスタマシン)のアセンブリ言語の出力
    は、難しそうだったからです
●   JVMはスタックマシンであり、仕組みが単純かつ
    マルチプラットホーム、しかもそこそこ実用的!
●   JVMの価値は、ライブラリにあると思います




                               9
自作コンパイラ
                 使用ツール
●   Jasmin
    –   Javaのクラスファイルを生成できるアセンブラ
    –   文法は、javap -Cで逆アセンブルしたときと同じような形式
●   Jay
    –   パーサ・ジェネレータ(bisonのJava版)
    –   Javaのソースコードとして、構文解析器を生成
●   JFlex
    –   レキシカル・アナライザ・ジェネレータ(flexのJava版)
    –   Javaのソースコードとして、字句解析器を生成


                                          10
自作コンパイラ
       概略図


   自作コンパイラ       Javaアセンブラ
                 Javaアセンブラ
   自作コンパイラ
                    Jasmin
                     Jasmin




自作言語の
自作言語の     Jasmin用
           Jasmin用      Java
                         Java
ソースコード
ソースコード   アセンブリコード
         アセンブリコード     クラスファイル
                      クラスファイル


                                11
自作コンパイラ
                       文法
●   今のところ、以下の文法規則のみです
    list  :
          |   list inum EOL
          |   list print inum EOL { 文字を出力 }
          ;
    inum :    expr
          ;
    expr :    expr ADDOP expr { 加算・減算命令の生成 }
          |   expr MULOP expr { 乗算・除算・剰余命令の生成 }
          |   NUMBER          { 数値をスタックに積む命令の生成 }
          ;
    print :   PRINT { プリントオブジェクトをスタックに積む命令の生成 }
          ;




                                                    12
自作コンパイラ
                 ソースコード例
●   自作言語のソースコード
    print 2 + 3 * 5


                      ・・・しょぼいですね、はい




                                      13
自作コンパイラ
           アセンブリコードの生成
●   コンパイルして生成されたアセンブリコード
    .class public KCTest
    .super java/lang/Object
    .method public <init>()V
      aload_0
      invokenonvirtual java/lang/Object/<init>()V
      return
    .end method
    .method public static main([Ljava/lang/String;)V
      .limit stack 5
      getstatic java/lang/System/out Ljava/io/PrintStream;
      ldc 2
      ldc 3
      ldc 5
      imul
      iadd
      invokevirtual java/io/PrintStream/println(I)V
      return
    .end method
                                                             14
自作コンパイラ
アセンブルしてクラスファイル生成
●   無事にクラスファイルを生成することができます。
    $ java -jar jasmin.jar asm.j
    Generated: KCTest.class
●   実行結果
    $ java KCTest
    17
●   演算子の優先度を考えて、正しく構文解析をでき
    たようです




                                   15
自作コンパイラ
                 逆コンパイル
●   生成したクラスファイルをjd-guiを用いて、逆コンパ
    イルしてみました
    public class KCTest
    {
      public static void main(String[] paramArrayOfString)
      {
        System.out.println(2 + 3 * 5);
      }
    }



●   (2 + 3 * 5)は、通常コンパイル時に計算されるの
    で、異質なものであると分かりますね

                                                             16
自作コンパイラ
            今後の課題
●   変数宣言ができるようにする
●   スタックサイズの自動的な決定
           でも、めんどくさいから、もうやらないかも・・・
                        うえたさん@がんばらない




                                       17
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                18
C言語のお話に
 入る前に・・・

           19
C言語のお話に入る前に・・・
         知識確認
●   実行バイナリが出来るまでの手順です
      Cソースコード
      Cソースコード
                プリプロセス
                プリプロセス

      Cプリプロセス
      Cプリプロセス
       ソースコード
       ソースコード   コンパイル
                コンパイル


     アセンブリコード
     アセンブリコード
                アセンブル
                アセンブル

      オブジェクト
      オブジェクト
       ファイル
       ファイル      リンク
                 リンク

        実行
        実行
       バイナリ
       バイナリ              20
C言語のお話に入る前に・・・
         知識確認
●   具体的には、こういうコマンドを用います
       foo.c
        foo.c    $ gcc -E foo.c -o foo.i
                 $ gcc -E foo.c -o foo.i

       foo.i
        foo.i
                 $ gcc -S foo.i -o foo.s
                 $ gcc -S foo.i -o foo.s

       foo.s
        foo.s
                 $ gcc -c foo.s -o foo.o
                 $ gcc -c foo.s -o foo.o

       foo.o
        foo.o
                 $ gcc foo.o -o foo.out
                 $ gcc foo.o -o foo.out

      foo.out
       foo.out                             21
さて、本題です


          22
const修飾子
             意義
●   const修飾子は、プログラムの書き手のためにあ
    るわけではないと思っています!
●   どちらかといえば・・・
     – 読み手のため
     – コンパイラの最適化のため
●   Immutable(不変)であることは強力です!!




                                23
const修飾子
            constポインタ(1)
●   関数の引数でRead onlyなポインタ変数(と参照
    変数)には、constを付けましょう!
    int add(const int *a, const int *b) {
      return *a + *b;
    }
    int add(const int &a, const int &b) {
      return a + b;
    }

●   読み手にとって、非常に読みやすくなります!


                                            24
const修飾子
                   constポインタ(2)
●   const int *a と int *const a の違い?
    –   const int *a は、指している先(value)へのconst性の付与
        ●   OK: a++;
         ● NG: (*a)++;


    –   int *const a は、それ以外を指せないようにする(addressへのconst
        性の付与)。指している先の値は変更可能。
        ●   NG: a++;
        ●   OK: (*a)++;
●   const int *const a とかもできます
●   const int *const *const b なんていうのも・・・

                                                       25
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                26
リンケージ(extern, static)
           基本
●   リンケージを意識して書くのは、分割コンパイルの
    基本です
●   extern記憶クラス指定子とstatic記憶クラス指定
    子というものがあります
●   関数内static変数とグローバルstatic変数のstatic
    の意味は異なります




                                       27
リンケージ(extern, static)
 分割コンパイルって?




                        28
リンケージ(extern, static)
       分割コンパイルって?
●   複数のソースファイルを書いて、最終的にそれら
    のオブジェクトファイルをドッキングすることです




                              29
リンケージ(extern, static)
        分割コンパイルって?
●   複数のソースファイルを書いて、最終的にそれら
    のオブジェクトファイルをドッキングリンクすること
    です
    $ gcc akane.o aoi.o -o vividblue.out




                                           30
リンケージ(extern, static)
            extern
●   『実体は別のところにある』という宣言です
●   関数プロトタイプには、自動で付与されます
    extern void foo();   // 書いてもいいが、書かない場合と変わらない
    void bar();          // externは省略してよい


●   主に、ヘッダファイルに書かれ、グローバル変数
    の実体の存在を知らせるのに使われます
●   外部に公開したい変数、関数につけます
    extern int foo;



                                                   31
リンケージ(extern, static)
            static
●   static・・・性的?




                               32
リンケージ(extern, static)
              static
●   static・・・性的静的
●   C言語のstaticは、意味合いが分かりにくいです
●   別の名称を使えばいいのに、と思ったり
    –   externの対義語としてinternとかね


                            うるさいよ、
                           このエロスが!!


                                      33
リンケージ(extern, static)
       static(グローバル)(1)
●   グローバルなstatic変数は、このソース内でしか
    使いませんよ、という宣言です
●   Javaでいうprivate変数みたいなものです
●   外部に公開しない、一時的なユーティリティ関数
    や、内だけで使用したいグローバル変数に使いま
    しょう
●   当然、ヘッダファイルに書くことはないです



                                34
リンケージ(extern, static)
          static(グローバル)(2)
●   staticは最適化の面でも恩恵があります
●   gccの-finline-functionsオプションは単純なstatic
    関数をinline展開してくれます
    –   (gccはinline使えるじゃん、とツッコまないこと)
●   static const変数は、コンパイルされると、変数とし
    ては消えます               \アッカリ~ン/




                                            35
リンケージ(extern, static)
           static(関数内)
●   関数内static変数は、関数単位で状態を保存する
    ための機構です
    int funcion(void) {
      static int a = 0;   // 初めてこの関数が呼ばれたときのみ初期化される
      return ++a;         // 関数が呼ばれるたびに、返す値が1ずつ増えていく
    }


●   呼び出す毎に挙動を変えることができますね!
    void function(void) {
      static int a = 0;
      if ((a++ & 1) == 0) {
        printf(“foon”);
      } else {
        printf(“barn”);
      }
    }

                                                       36
リンケージ(extern, static)
         まとめ

                     キーワード           意味
            static           変数の実体(外部に公開しない)
 グローバル変数    キーワードなし          変数の実体(外部に公開する)
            extern           変数の宣言(実体ではない)
            static           外部に公開しない関数
  関数の実体     キーワードなし          外部に公開する関数
            extern           外部に公開する関数
            static           外部に公開しない関数のプロトタイプ
関数のプロトタイプ宣言 キーワードなし          外部に公開する関数のプロトタイプ
            extern           外部に公開する関数のプロトタイプ



                                               37
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                38
ヘッダファイル



    あなたは
 正しいヘッダファイルの
書き方ができていますか?


               39
ヘッダファイル
           書き方
●   基本的に実体は書きません
●   インターフェースを記述するのがヘッダファイルで
    す
●   関数定義や変数宣言をしないでください
●   外部に公開するものを.hに、その実体を.cに書く
    のが基本です!




                               40
ヘッダファイル
              何を書くの?
●   具体的には、
    –   マクロ
    –   extern変数宣言
    –   プロトタイプ宣言
    –   列挙体定義(enum)
    –   型定義(typedef)
    –   (インライン関数)




                        41
ヘッダファイル
                   C++なお話
●   .h と .hppの違いって何?
    –   .hpp = .h + .cppと思ってください
    –   つまり、クラスの実体も書いたヘッダファイルが.hppです
    –   通常は.hと.cppに分割し、以下のようにするのが好ましいです
        ●
            .hにはクラス宣言
        ●   .cppには実装
●   C++では、テンプレートもヘッダに書くようですね




                                          42
ヘッダファイル
        インクルードガード
●   多重インクルードを防ぐようにしていますか?
●   多重インクルードをして、マクロなどが複数回定義
    がされると、コンパイルエラーが出ます
●   分割コンパイルするときのヘッダの管理は大変で
    すよね!
●   なので、インクルードガードをしましょう!




                              43
ヘッダファイル
        インクルードガードの書き方
●   こんなやつをヘッダに書きましょう↓
    #ifndef HOGE_H
    #define HOGE_H
       …
    #endif

●   もしくは、新しい方法で↓
    #pragma once

    –   #ifndef, #define, #endifはプリプロセッサが処理
    –   #pragma onceはコンパイラが処理


                                              44
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                45
関数定義



問題のあるものを
 紹介します

           46
関数定義
                        case1:
    int function() {
      return 1;
    }

●   問題点
    –   引数が無いとき、()と書いていること
●   アドバイス
    –   引数が無い場合は、引数にvoidと書きましょう
        ● (ただし、C++では、()と書くと引数無しとみなされます)
    –   コンパイラの引数の型検査が受けられなくなります


                                          47
関数定義
                        case2:
    function(void) {
      return 0xff;
    }

●
    問題点
    –   返り値の型を省略していること
●   アドバイス
    –   返り値の型を省略すると、intを返すと推論されますが、行儀が悪
        いので止めましょう
    –   これも、コンパイラの返り値の型検査が受けられなくなります
    –   省略がカッコイイと思っているのは、厨二病です


                                          48
アウトライン
●   自作コンパイラ(まだまだ未完成)
●   C言語マナー
    –   const修飾子
    –   リンケージ(extern, static)
    –   ヘッダファイルの書き方
    –   関数定義
    –   個人的に気を付けているコーディングマナー



                                49
個人的に気をつけている
        コーディングマナー
●   変数の使いまわしをしない
●   変数の寿命(スコープ)は可能な限り短く
●   演算子の前と後には1スペース空ける
●   if, for, switch, whileなどの丸括弧の前と後に1ス
    ペース
●   エラー処理はガード条件を用いて、ネストを深くし
    ない
●   1つの関数を大きくしすぎない

                                          50
個人的に気をつけている
             コーディングマナー
●   コンパイラの警告レベルを上げるのもいいですね
●   gccだと以下のオプションがあります
    –   -Wall:一般的に注意すべき警告を全て出力します
    –   -Wextra:かなりおせっかいな警告も出力します
        ●   gcc3.xでは-Wオプションなので注意
    –   -pedantic:厳密なANSI CおよびISO C++により要求される警
        告をすべて出力します
●   -pedanticはやりすぎですが、-Wall、-Wextraをク
    リアすると、いい感じだと思います

                                                 51
以上で、
発表終了です

         52
御清聴
 ありがとう
ございました・・・

            53
でも・・・?


         54
俺の発表が
こんな平和なもので
終わるわけがない

            55
ってことで、


         56
黒魔術を
紹介していきます

           57
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         58
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         59
インラインアセンブラ
            概要
●   C/C++といえば、アセンブラですよね!
●   とはいえ、アセンブラは難しい・・・
●   でも、アセンブリコードはパフォーマンスチューニ
    ングの参考にはなりますよね
●   でも、ある部分のコードがどのアセンブリコードに
    対応するのか確認するのは面倒・・・




                              60
インラインアセンブラ
    インラインアセンブラのコメント
●   そんなときに、インラインアセンブラ!!
●   インラインアセンブラで、アセンブラのコメントを入
    れると確認しやすいです
●   インラインアセンブラの記述方法は、コンパイラに
    よって異なるので注意してください
●   インラインアセンブラに間違ったコードを入れる
    と、コンパイル時ではなく、アセンブル時にエラー
    が出ます


                               61
インラインアセンブラ
           アセンブラコメント挿入
●   以下のコード(抜粋)をコンパイル
    // アセンブリコードのコメントは#
    asm("# ========== loop begin ==========");
    for (i = 0; i < 10; i++) {
      puts("Hello");
    }
    asm("# ========== loop end   ==========");


●   コンパイルコマンド
    $ gcc -S loop.c -o loop.s




                                                 62
インラインアセンブラ
            コンパイル後のコード
●   コンパイル結果
    –   アセンブリコードにコメントが入っていますね
     # 12 "loop.c" 1
      # ========== loop begin ==========
     # 0 "" 2
    /NO_APP
      movl $0, 28(%esp)
      jmp L2
    L3:
      movl $LC0, (%esp)
      call _puts
      incl 28(%esp)
    L2:
      cmpl $9, 28(%esp)
      jle L3
    /APP
     # 16 "loop.c" 1
      # ========== loop end   ==========
     # 0 "" 2
                                           63
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         64
ビットフィールド
            ビットフィールドとは?
●   C言語の特殊な文法(機能)として、ビビッドビット
    フィールドというものがあります
●   あまり使われませんが、組み込み系などで使わ
    れることがあります
●
    これを用いると、以下のようなビット演算子を用い
    たビットをON・OFFする作業が不要となります
    enum bit_flags {
       BIT_A = 0x01, BIT_B = 0x02
    };

    int main(void) {
      int flag;
      flag |= BIT_A; // 1ビット目のビットをセット
      flag &= ~BIT_B; // 2ビット目のビットをクリア
      printf(“flag = %dn”, flag);
      return EXIT_SUCCESS;               65
    }
ビットフィールド
         ビットフィールドの使い方
●   ビットフィールドは構造体の一部として用います
●   構造体全体のサイズは、int型のn倍になります
●   構造体のメンバにunsigned intと書きますが、そ
    のメンバにunsigned int分の領域が確保されるわ
    けではありません
    // 構造体全体でunsigned int型のサイズにアラインされる
    struct {
      unsigned int a : 1; // 1ビットの領域の確保
      unsigned int b : 1; // 1ビットの領域の確保
    } bf;
    int main(void) {
      bf.a = 1; // 1ビット目のビットをセット
      bf.b = 0; // 2ビット目のビットをクリア
      printf("sizeof(bf) = %dn", sizeof(bf));
      printf("bf = %dn", bf); // 1と表示
      return EXIT_SUCCESS;                       66
    }
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         67
関数ポインタ
                    概要
●   関数ポインタは、関数をモノとして扱うための手段
    です
●   関数型言語の『高階関数』を実現することができ
    ます
●   変数、引数が名詞、関数が動詞というなら、関数
    ポインタは動名詞というところでしょうか
●   <stdlib.h>のqsortの第4引数は関数ポインタです
    // qsortのプロトタイプ
    void qsort(void *base, size_t num, size_t size,
               int (*compare)(const void*, const void*))


                                                           68
関数ポインタ
    構造体を用いた見た目C++コード
●   以下のようなコードだと、パッと見た感じC++っぽ
    く見えますよね
    typedef struct {
      int (*add)(int, int);
      int (*sub)(int, int);
    } obj_st;

    int add(int a, int b) {
      return a + b;
    }

    int sub(int a, int b) {
      return a - b;
    }

    int main(void) {
      obj_st os = {add, sub};
      printf("2 + 5 = %dn", os.add(2, 5));
      printf("9 - 6 = %dn", os.sub(9, 6));
      return EXIT_SUCCESS;                    69
    }
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         70
GNU拡張文法
                 一例
●   gcc, g++のGNU拡張機能には、以下のようなも
    のがあります
    –   複文を式にする
    –   関数内関数定義(g++では不可能)
    –   typeof演算子
    –   型を表す変数




                                 71
GNU拡張文法
             複文を式化する
●   この機能は、複文({ }の部分)を丸括弧でくくること
    により、その複文が式になるというものです
●   式の値は、最後の複文の値になります
    // この例だと、この式化した複文の値は1
    ({
       if (a == 0) {
          printf(“foon”);
       } else {
          printf(“barn”);
       }
       1;
    })




                                 72
GNU拡張文法
              強制インライン展開
●   複文を式化する機能をマクロに使おう!
●   2数の内、最大値を返す関数をマクロでインライン
    化した例です
    int max(int a, int b) {   #define max(a, b) ({   
      if (a >= b) {             typeof(a) _a = a;    
        return a;               typeof(b) _b = b;    
      } else {                  typeof(a) max;       
        return b;               if (_a >= _b) {      
      }                           max = _a;          
    }                           } else {             
                                  max = _b;          
                                }                    
                                max;                 
                              })



                                                         73
黒魔術のアウトライン
●
    インラインアセンブラ
    –   アセンブラのコメント挿入
●
    ビットフィールド
    –   ビットフィールドの使い方
●
    関数ポインタ
    –   C++ライクなコード
●   GNU拡張文法
    –   強制インライン展開
●
    三項演算子とカンマ演算子
    –   トリッキーコード


                         74
三項演算子とカンマ演算子
        三項演算子とは?
●   三項演算子(条件演算子)は以下のような形式で記述
    されます
    <条件> ? <条件がtrueのときの値> : <条件がfalseのときの値>

●
    絶対値を表す三項演算子は以下の通り
    abs_value = x > 0 ? x : -x;

●   簡単な条件分岐であれば、if~else文より簡潔に記述
    できます
●
    三項演算子は、式でありながら条件分岐が可能で
    す!

                                              75
三項演算子とカンマ演算子
          カンマ演算子とは?
●   カンマ演算子とは、複数の式を1つの式として扱う
    手段です
●   以下のように記述したとき、式全体の値は値nとな
    ります(各値は1度ずつ評価されます)
    (値1, 値2, 値3, … , 値n)


●   以下のように記述したとき、xに代入されるのは3
    となります
    x = (1, printf(“foo”), 2, printf(“bar”), 3);




                                                   76
三項演算子とカンマ演算子
      THE 黒魔術!! ~FizzBuzz~
●   以下は、FizzBuzzをトリッキーに書いた例です
●   三項演算子とカンマ演算子があれば何でもできま
    す!!(誇張あり)
    int main(void) {
      static const int MAX = 100;
      int i;
      for (i = 0; i < MAX; i++) {
        puts((printf("i = %2d : ", i),
              i % 15 == 0 ? "FizzBuzz"
                          : i % 5 == 0 ? "Buzz"
                                       : i % 3 == 0 ? "Fizz"
                                                    : "")
        );
      }
      return EXIT_SUCCESS;
    }

                                                               77
参考文献
●   プログラミング言語C 第2版
●   C言語 入門書の次に読む本 [改訂新版]




                           78
参考文献
●   分割コンパイルとリンケージ
    –   http://www.cc.kyoto-su.ac.jp/~hxm/cstext/prog06.html
●   GCC some extensions
    –   http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/gccextend.html
●
    トリッキーコードネット
    –   http://tricky-code.net/
●
    八角研究所
    –   http://www.hakkaku.net/articles/20090318-400




                                                                             79
今度こそ、本当に
   御清聴
  ありがとう
 ございました!
   m(__)m
            80

More Related Content

What's hot

中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexprGenya Murakami
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析Yuki Mizuno
 
C++のビルド高速化について
C++のビルド高速化についてC++のビルド高速化について
C++のビルド高速化についてAimingStudy
 
お前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのかお前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのかKousuke Ebihara
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Takashi Hoshino
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングKohsuke Yuasa
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方Shigenori Sagawa
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 
イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術Kohsuke Yuasa
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost testKohsuke Yuasa
 
Cargo makeを使ってみた話
Cargo makeを使ってみた話Cargo makeを使ってみた話
Cargo makeを使ってみた話emakryo
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
ErlangでErlagVM上で動く言語の作り方
ErlangでErlagVM上で動く言語の作り方ErlangでErlagVM上で動く言語の作り方
ErlangでErlagVM上で動く言語の作り方osamu kimura
 
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor Skochinsky
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor SkochinskyインテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor Skochinsky
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor SkochinskyCODE BLUE
 

What's hot (20)

中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析
 
C++のビルド高速化について
C++のビルド高速化についてC++のビルド高速化について
C++のビルド高速化について
 
最速C# 7.x
最速C# 7.x最速C# 7.x
最速C# 7.x
 
お前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのかお前は PHP の歴史的な理由の数を覚えているのか
お前は PHP の歴史的な理由の数を覚えているのか
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4Effective Modern C++ 勉強会#1 Item3,4
Effective Modern C++ 勉強会#1 Item3,4
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 
イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術イマドキC++erのモテカワリソース管理術
イマドキC++erのモテカワリソース管理術
 
systemd 再入門
systemd 再入門systemd 再入門
systemd 再入門
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
 
Cargo makeを使ってみた話
Cargo makeを使ってみた話Cargo makeを使ってみた話
Cargo makeを使ってみた話
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
ErlangでErlagVM上で動く言語の作り方
ErlangでErlagVM上で動く言語の作り方ErlangでErlagVM上で動く言語の作り方
ErlangでErlagVM上で動く言語の作り方
 
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor Skochinsky
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor SkochinskyインテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor Skochinsky
インテルMEの秘密 - チップセットに隠されたコードと、それが一体何をするかを見出す方法 - by イゴール・スコチンスキー - Igor Skochinsky
 

Similar to 第2回勉強会スライド

Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
第1回勉強会スライド
第1回勉強会スライド第1回勉強会スライド
第1回勉強会スライドkoturn 0;
 
20130316 プログラミング言語Go
20130316 プログラミング言語Go20130316 プログラミング言語Go
20130316 プログラミング言語GoYoshifumi Yamaguchi
 
20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)Yoshifumi Yamaguchi
 
Code Reading at Security and Programming camp 2011
Code Reading at Security and Programming camp 2011 Code Reading at Security and Programming camp 2011
Code Reading at Security and Programming camp 2011 Hiro Yoshioka
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code readingHiro Yoshioka
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門伸男 伊藤
 
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践LINE Corporation
 
【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門sandai
 
Cプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めCプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めMITSUNARI Shigeo
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようShinsuke Sugaya
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49shoma h
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
xv6から始めるSPIN入門
xv6から始めるSPIN入門xv6から始めるSPIN入門
xv6から始めるSPIN入門Ryousei Takano
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成Akineko Shimizu
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesNoritada Shimizu
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform信之 岩永
 

Similar to 第2回勉強会スライド (20)

Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
第1回勉強会スライド
第1回勉強会スライド第1回勉強会スライド
第1回勉強会スライド
 
20130316 プログラミング言語Go
20130316 プログラミング言語Go20130316 プログラミング言語Go
20130316 プログラミング言語Go
 
20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)
 
Code Reading at Security and Programming camp 2011
Code Reading at Security and Programming camp 2011 Code Reading at Security and Programming camp 2011
Code Reading at Security and Programming camp 2011
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code reading
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践
コンパイルターゲット言語としてのWebAssembly、そしてLINEでの実践
 
【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門
 
Cプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めCプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧め
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
Pythonista による Pythonista のための Scala 紹介 in BPStudy #49
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
xv6から始めるSPIN入門
xv6から始めるSPIN入門xv6から始めるSPIN入門
xv6から始めるSPIN入門
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform
 

第2回勉強会スライド

  • 5. まずは、自己紹介から 名前:koturn 0; 趣味:数学、プログラミング エディタ:vim派 言語:C/C++/C#/Java/Python /Ruby/Javascipt/common LISP /elisp/Vim script 5
  • 6. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 6
  • 7. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 7
  • 8. 自作コンパイラ 概要 ● プログラミング言語を作ろうという試みです ● 実用的になるように、Javaのクラスファイル (.class)を出力するようにしています 8
  • 9. 自作コンパイラ なぜJVMをターゲットに? ● 実マシン(レジスタマシン)のアセンブリ言語の出力 は、難しそうだったからです ● JVMはスタックマシンであり、仕組みが単純かつ マルチプラットホーム、しかもそこそこ実用的! ● JVMの価値は、ライブラリにあると思います 9
  • 10. 自作コンパイラ 使用ツール ● Jasmin – Javaのクラスファイルを生成できるアセンブラ – 文法は、javap -Cで逆アセンブルしたときと同じような形式 ● Jay – パーサ・ジェネレータ(bisonのJava版) – Javaのソースコードとして、構文解析器を生成 ● JFlex – レキシカル・アナライザ・ジェネレータ(flexのJava版) – Javaのソースコードとして、字句解析器を生成 10
  • 11. 自作コンパイラ 概略図 自作コンパイラ Javaアセンブラ Javaアセンブラ 自作コンパイラ Jasmin Jasmin 自作言語の 自作言語の Jasmin用 Jasmin用 Java Java ソースコード ソースコード アセンブリコード アセンブリコード クラスファイル クラスファイル 11
  • 12. 自作コンパイラ 文法 ● 今のところ、以下の文法規則のみです list : | list inum EOL | list print inum EOL { 文字を出力 } ; inum : expr ; expr : expr ADDOP expr { 加算・減算命令の生成 } | expr MULOP expr { 乗算・除算・剰余命令の生成 } | NUMBER { 数値をスタックに積む命令の生成 } ; print : PRINT { プリントオブジェクトをスタックに積む命令の生成 } ; 12
  • 13. 自作コンパイラ ソースコード例 ● 自作言語のソースコード print 2 + 3 * 5 ・・・しょぼいですね、はい 13
  • 14. 自作コンパイラ アセンブリコードの生成 ● コンパイルして生成されたアセンブリコード .class public KCTest .super java/lang/Object .method public <init>()V aload_0 invokenonvirtual java/lang/Object/<init>()V return .end method .method public static main([Ljava/lang/String;)V .limit stack 5 getstatic java/lang/System/out Ljava/io/PrintStream; ldc 2 ldc 3 ldc 5 imul iadd invokevirtual java/io/PrintStream/println(I)V return .end method 14
  • 15. 自作コンパイラ アセンブルしてクラスファイル生成 ● 無事にクラスファイルを生成することができます。 $ java -jar jasmin.jar asm.j Generated: KCTest.class ● 実行結果 $ java KCTest 17 ● 演算子の優先度を考えて、正しく構文解析をでき たようです 15
  • 16. 自作コンパイラ 逆コンパイル ● 生成したクラスファイルをjd-guiを用いて、逆コンパ イルしてみました public class KCTest { public static void main(String[] paramArrayOfString) { System.out.println(2 + 3 * 5); } } ● (2 + 3 * 5)は、通常コンパイル時に計算されるの で、異質なものであると分かりますね 16
  • 17. 自作コンパイラ 今後の課題 ● 変数宣言ができるようにする ● スタックサイズの自動的な決定 でも、めんどくさいから、もうやらないかも・・・ うえたさん@がんばらない 17
  • 18. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 18
  • 20. C言語のお話に入る前に・・・ 知識確認 ● 実行バイナリが出来るまでの手順です Cソースコード Cソースコード プリプロセス プリプロセス Cプリプロセス Cプリプロセス ソースコード ソースコード コンパイル コンパイル アセンブリコード アセンブリコード アセンブル アセンブル オブジェクト オブジェクト ファイル ファイル リンク リンク 実行 実行 バイナリ バイナリ 20
  • 21. C言語のお話に入る前に・・・ 知識確認 ● 具体的には、こういうコマンドを用います foo.c foo.c $ gcc -E foo.c -o foo.i $ gcc -E foo.c -o foo.i foo.i foo.i $ gcc -S foo.i -o foo.s $ gcc -S foo.i -o foo.s foo.s foo.s $ gcc -c foo.s -o foo.o $ gcc -c foo.s -o foo.o foo.o foo.o $ gcc foo.o -o foo.out $ gcc foo.o -o foo.out foo.out foo.out 21
  • 23. const修飾子 意義 ● const修飾子は、プログラムの書き手のためにあ るわけではないと思っています! ● どちらかといえば・・・ – 読み手のため – コンパイラの最適化のため ● Immutable(不変)であることは強力です!! 23
  • 24. const修飾子 constポインタ(1) ● 関数の引数でRead onlyなポインタ変数(と参照 変数)には、constを付けましょう! int add(const int *a, const int *b) { return *a + *b; } int add(const int &a, const int &b) { return a + b; } ● 読み手にとって、非常に読みやすくなります! 24
  • 25. const修飾子 constポインタ(2) ● const int *a と int *const a の違い? – const int *a は、指している先(value)へのconst性の付与 ● OK: a++; ● NG: (*a)++; – int *const a は、それ以外を指せないようにする(addressへのconst 性の付与)。指している先の値は変更可能。 ● NG: a++; ● OK: (*a)++; ● const int *const a とかもできます ● const int *const *const b なんていうのも・・・ 25
  • 26. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 26
  • 27. リンケージ(extern, static) 基本 ● リンケージを意識して書くのは、分割コンパイルの 基本です ● extern記憶クラス指定子とstatic記憶クラス指定 子というものがあります ● 関数内static変数とグローバルstatic変数のstatic の意味は異なります 27
  • 29. リンケージ(extern, static) 分割コンパイルって? ● 複数のソースファイルを書いて、最終的にそれら のオブジェクトファイルをドッキングすることです 29
  • 30. リンケージ(extern, static) 分割コンパイルって? ● 複数のソースファイルを書いて、最終的にそれら のオブジェクトファイルをドッキングリンクすること です $ gcc akane.o aoi.o -o vividblue.out 30
  • 31. リンケージ(extern, static) extern ● 『実体は別のところにある』という宣言です ● 関数プロトタイプには、自動で付与されます extern void foo(); // 書いてもいいが、書かない場合と変わらない void bar(); // externは省略してよい ● 主に、ヘッダファイルに書かれ、グローバル変数 の実体の存在を知らせるのに使われます ● 外部に公開したい変数、関数につけます extern int foo; 31
  • 32. リンケージ(extern, static) static ● static・・・性的? 32
  • 33. リンケージ(extern, static) static ● static・・・性的静的 ● C言語のstaticは、意味合いが分かりにくいです ● 別の名称を使えばいいのに、と思ったり – externの対義語としてinternとかね うるさいよ、 このエロスが!! 33
  • 34. リンケージ(extern, static) static(グローバル)(1) ● グローバルなstatic変数は、このソース内でしか 使いませんよ、という宣言です ● Javaでいうprivate変数みたいなものです ● 外部に公開しない、一時的なユーティリティ関数 や、内だけで使用したいグローバル変数に使いま しょう ● 当然、ヘッダファイルに書くことはないです 34
  • 35. リンケージ(extern, static) static(グローバル)(2) ● staticは最適化の面でも恩恵があります ● gccの-finline-functionsオプションは単純なstatic 関数をinline展開してくれます – (gccはinline使えるじゃん、とツッコまないこと) ● static const変数は、コンパイルされると、変数とし ては消えます \アッカリ~ン/ 35
  • 36. リンケージ(extern, static) static(関数内) ● 関数内static変数は、関数単位で状態を保存する ための機構です int funcion(void) { static int a = 0; // 初めてこの関数が呼ばれたときのみ初期化される return ++a; // 関数が呼ばれるたびに、返す値が1ずつ増えていく } ● 呼び出す毎に挙動を変えることができますね! void function(void) { static int a = 0; if ((a++ & 1) == 0) { printf(“foon”); } else { printf(“barn”); } } 36
  • 37. リンケージ(extern, static) まとめ キーワード 意味 static 変数の実体(外部に公開しない) グローバル変数 キーワードなし 変数の実体(外部に公開する) extern 変数の宣言(実体ではない) static 外部に公開しない関数 関数の実体 キーワードなし 外部に公開する関数 extern 外部に公開する関数 static 外部に公開しない関数のプロトタイプ 関数のプロトタイプ宣言 キーワードなし 外部に公開する関数のプロトタイプ extern 外部に公開する関数のプロトタイプ 37
  • 38. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 38
  • 39. ヘッダファイル あなたは 正しいヘッダファイルの 書き方ができていますか? 39
  • 40. ヘッダファイル 書き方 ● 基本的に実体は書きません ● インターフェースを記述するのがヘッダファイルで す ● 関数定義や変数宣言をしないでください ● 外部に公開するものを.hに、その実体を.cに書く のが基本です! 40
  • 41. ヘッダファイル 何を書くの? ● 具体的には、 – マクロ – extern変数宣言 – プロトタイプ宣言 – 列挙体定義(enum) – 型定義(typedef) – (インライン関数) 41
  • 42. ヘッダファイル C++なお話 ● .h と .hppの違いって何? – .hpp = .h + .cppと思ってください – つまり、クラスの実体も書いたヘッダファイルが.hppです – 通常は.hと.cppに分割し、以下のようにするのが好ましいです ● .hにはクラス宣言 ● .cppには実装 ● C++では、テンプレートもヘッダに書くようですね 42
  • 43. ヘッダファイル インクルードガード ● 多重インクルードを防ぐようにしていますか? ● 多重インクルードをして、マクロなどが複数回定義 がされると、コンパイルエラーが出ます ● 分割コンパイルするときのヘッダの管理は大変で すよね! ● なので、インクルードガードをしましょう! 43
  • 44. ヘッダファイル インクルードガードの書き方 ● こんなやつをヘッダに書きましょう↓ #ifndef HOGE_H #define HOGE_H … #endif ● もしくは、新しい方法で↓ #pragma once – #ifndef, #define, #endifはプリプロセッサが処理 – #pragma onceはコンパイラが処理 44
  • 45. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 45
  • 47. 関数定義 case1: int function() { return 1; } ● 問題点 – 引数が無いとき、()と書いていること ● アドバイス – 引数が無い場合は、引数にvoidと書きましょう ● (ただし、C++では、()と書くと引数無しとみなされます) – コンパイラの引数の型検査が受けられなくなります 47
  • 48. 関数定義 case2: function(void) { return 0xff; } ● 問題点 – 返り値の型を省略していること ● アドバイス – 返り値の型を省略すると、intを返すと推論されますが、行儀が悪 いので止めましょう – これも、コンパイラの返り値の型検査が受けられなくなります – 省略がカッコイイと思っているのは、厨二病です 48
  • 49. アウトライン ● 自作コンパイラ(まだまだ未完成) ● C言語マナー – const修飾子 – リンケージ(extern, static) – ヘッダファイルの書き方 – 関数定義 – 個人的に気を付けているコーディングマナー 49
  • 50. 個人的に気をつけている コーディングマナー ● 変数の使いまわしをしない ● 変数の寿命(スコープ)は可能な限り短く ● 演算子の前と後には1スペース空ける ● if, for, switch, whileなどの丸括弧の前と後に1ス ペース ● エラー処理はガード条件を用いて、ネストを深くし ない ● 1つの関数を大きくしすぎない 50
  • 51. 個人的に気をつけている コーディングマナー ● コンパイラの警告レベルを上げるのもいいですね ● gccだと以下のオプションがあります – -Wall:一般的に注意すべき警告を全て出力します – -Wextra:かなりおせっかいな警告も出力します ● gcc3.xでは-Wオプションなので注意 – -pedantic:厳密なANSI CおよびISO C++により要求される警 告をすべて出力します ● -pedanticはやりすぎですが、-Wall、-Wextraをク リアすると、いい感じだと思います 51
  • 58. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 58
  • 59. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 59
  • 60. インラインアセンブラ 概要 ● C/C++といえば、アセンブラですよね! ● とはいえ、アセンブラは難しい・・・ ● でも、アセンブリコードはパフォーマンスチューニ ングの参考にはなりますよね ● でも、ある部分のコードがどのアセンブリコードに 対応するのか確認するのは面倒・・・ 60
  • 61. インラインアセンブラ インラインアセンブラのコメント ● そんなときに、インラインアセンブラ!! ● インラインアセンブラで、アセンブラのコメントを入 れると確認しやすいです ● インラインアセンブラの記述方法は、コンパイラに よって異なるので注意してください ● インラインアセンブラに間違ったコードを入れる と、コンパイル時ではなく、アセンブル時にエラー が出ます 61
  • 62. インラインアセンブラ アセンブラコメント挿入 ● 以下のコード(抜粋)をコンパイル // アセンブリコードのコメントは# asm("# ========== loop begin =========="); for (i = 0; i < 10; i++) { puts("Hello"); } asm("# ========== loop end =========="); ● コンパイルコマンド $ gcc -S loop.c -o loop.s 62
  • 63. インラインアセンブラ コンパイル後のコード ● コンパイル結果 – アセンブリコードにコメントが入っていますね # 12 "loop.c" 1 # ========== loop begin ========== # 0 "" 2 /NO_APP movl $0, 28(%esp) jmp L2 L3: movl $LC0, (%esp) call _puts incl 28(%esp) L2: cmpl $9, 28(%esp) jle L3 /APP # 16 "loop.c" 1 # ========== loop end ========== # 0 "" 2 63
  • 64. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 64
  • 65. ビットフィールド ビットフィールドとは? ● C言語の特殊な文法(機能)として、ビビッドビット フィールドというものがあります ● あまり使われませんが、組み込み系などで使わ れることがあります ● これを用いると、以下のようなビット演算子を用い たビットをON・OFFする作業が不要となります enum bit_flags { BIT_A = 0x01, BIT_B = 0x02 }; int main(void) { int flag; flag |= BIT_A; // 1ビット目のビットをセット flag &= ~BIT_B; // 2ビット目のビットをクリア printf(“flag = %dn”, flag); return EXIT_SUCCESS; 65 }
  • 66. ビットフィールド ビットフィールドの使い方 ● ビットフィールドは構造体の一部として用います ● 構造体全体のサイズは、int型のn倍になります ● 構造体のメンバにunsigned intと書きますが、そ のメンバにunsigned int分の領域が確保されるわ けではありません // 構造体全体でunsigned int型のサイズにアラインされる struct { unsigned int a : 1; // 1ビットの領域の確保 unsigned int b : 1; // 1ビットの領域の確保 } bf; int main(void) { bf.a = 1; // 1ビット目のビットをセット bf.b = 0; // 2ビット目のビットをクリア printf("sizeof(bf) = %dn", sizeof(bf)); printf("bf = %dn", bf); // 1と表示 return EXIT_SUCCESS; 66 }
  • 67. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 67
  • 68. 関数ポインタ 概要 ● 関数ポインタは、関数をモノとして扱うための手段 です ● 関数型言語の『高階関数』を実現することができ ます ● 変数、引数が名詞、関数が動詞というなら、関数 ポインタは動名詞というところでしょうか ● <stdlib.h>のqsortの第4引数は関数ポインタです // qsortのプロトタイプ void qsort(void *base, size_t num, size_t size, int (*compare)(const void*, const void*)) 68
  • 69. 関数ポインタ 構造体を用いた見た目C++コード ● 以下のようなコードだと、パッと見た感じC++っぽ く見えますよね typedef struct { int (*add)(int, int); int (*sub)(int, int); } obj_st; int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int main(void) { obj_st os = {add, sub}; printf("2 + 5 = %dn", os.add(2, 5)); printf("9 - 6 = %dn", os.sub(9, 6)); return EXIT_SUCCESS; 69 }
  • 70. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 70
  • 71. GNU拡張文法 一例 ● gcc, g++のGNU拡張機能には、以下のようなも のがあります – 複文を式にする – 関数内関数定義(g++では不可能) – typeof演算子 – 型を表す変数 71
  • 72. GNU拡張文法 複文を式化する ● この機能は、複文({ }の部分)を丸括弧でくくること により、その複文が式になるというものです ● 式の値は、最後の複文の値になります // この例だと、この式化した複文の値は1 ({ if (a == 0) { printf(“foon”); } else { printf(“barn”); } 1; }) 72
  • 73. GNU拡張文法 強制インライン展開 ● 複文を式化する機能をマクロに使おう! ● 2数の内、最大値を返す関数をマクロでインライン 化した例です int max(int a, int b) { #define max(a, b) ({ if (a >= b) { typeof(a) _a = a; return a; typeof(b) _b = b; } else { typeof(a) max; return b; if (_a >= _b) { } max = _a; } } else { max = _b; } max; }) 73
  • 74. 黒魔術のアウトライン ● インラインアセンブラ – アセンブラのコメント挿入 ● ビットフィールド – ビットフィールドの使い方 ● 関数ポインタ – C++ライクなコード ● GNU拡張文法 – 強制インライン展開 ● 三項演算子とカンマ演算子 – トリッキーコード 74
  • 75. 三項演算子とカンマ演算子 三項演算子とは? ● 三項演算子(条件演算子)は以下のような形式で記述 されます <条件> ? <条件がtrueのときの値> : <条件がfalseのときの値> ● 絶対値を表す三項演算子は以下の通り abs_value = x > 0 ? x : -x; ● 簡単な条件分岐であれば、if~else文より簡潔に記述 できます ● 三項演算子は、式でありながら条件分岐が可能で す! 75
  • 76. 三項演算子とカンマ演算子 カンマ演算子とは? ● カンマ演算子とは、複数の式を1つの式として扱う 手段です ● 以下のように記述したとき、式全体の値は値nとな ります(各値は1度ずつ評価されます) (値1, 値2, 値3, … , 値n) ● 以下のように記述したとき、xに代入されるのは3 となります x = (1, printf(“foo”), 2, printf(“bar”), 3); 76
  • 77. 三項演算子とカンマ演算子 THE 黒魔術!! ~FizzBuzz~ ● 以下は、FizzBuzzをトリッキーに書いた例です ● 三項演算子とカンマ演算子があれば何でもできま す!!(誇張あり) int main(void) { static const int MAX = 100; int i; for (i = 0; i < MAX; i++) { puts((printf("i = %2d : ", i), i % 15 == 0 ? "FizzBuzz" : i % 5 == 0 ? "Buzz" : i % 3 == 0 ? "Fizz" : "") ); } return EXIT_SUCCESS; } 77
  • 78. 参考文献 ● プログラミング言語C 第2版 ● C言語 入門書の次に読む本 [改訂新版] 78
  • 79. 参考文献 ● 分割コンパイルとリンケージ – http://www.cc.kyoto-su.ac.jp/~hxm/cstext/prog06.html ● GCC some extensions – http://www-cms.phys.s.u-tokyo.ac.jp/~naoki/CIPINTRO/gccextend.html ● トリッキーコードネット – http://tricky-code.net/ ● 八角研究所 – http://www.hakkaku.net/articles/20090318-400 79
  • 80. 今度こそ、本当に 御清聴 ありがとう ございました! m(__)m 80