GCCのいくつかの特性

33546 ワード

文字列の表示形式
gccがサポートする文字列の表現形式
「xxx」「xxx」「xxx」は、この3つの文字列を1つに連結し、最後の文字列の末尾に「0」を追加するだけで、各文字列間のスペース記号も無視します.
attribute
_attribute__実はgcc独自の構文で、関数属性(Function Attribute)、変数属性(Variable Attribute)、タイプ属性(Type Attribute)を設定するための構文です
構文
attribute (parameter)
int a __attribute__ ((xxxxx)); 

構造タイプのプロパティ
struct info{
.....
} __attribute__ ((xxxxx)) sb;
  • aligned整列
  • //  struct fd        
    struct fd{
    ...
    }__sttribute__ ((align(4))) fd;
    
  • packedをpackedで修飾すると、1バイト整列
  • になる.
    typedef struct {
        char    version;
        int16_t sid;
        int32_t len;
        int64_t time;
    }__attribute__ ((packed)) Header;
    

    関数プロパティ(Function Attribute)
        noreturn
        noinline
        always_inline
        pure
        const
        nothrow
        sentinel
        format
        format_arg
        no_instrument_function
        section
        constructor
        destructor
        used
        unused
        deprecated
        weak
        malloc
        alias
        warn_unused_result
        nonnull 
    weak , alias
    
  • alias別名weak
  • //  
    int cpu_mmc_init(bd_t *bis) __attribute__((weak, alias("__def_mmc_init")));
    
  • 申明cpu_mmc_initは_def_mmc_initの別名
  • cpu_mmc_Initが定義されていない場合は、2__を使用します.def_mmc_init、定義があればcpu_を使用しますmmc_init自体.
  • __def_mmc_Init関数は必ず定義されています.
  • weakプロパティを指定:cpu_でもmmc_init関数は定義されていません.cpu_を呼び出します.mmc_Initコンパイラもエラーを報告しない
  • weakは一般的にalias属性と連用されます.
  • unusedは、この変数または関数が使用されていない場合でも警告情報を出力しないことを指定します.
  • static void func(void) __attribute__((unused));
    static void func(int a,int b __attribute__((unused)),int c);
    
  • section指定リンクsection
  • この関数または変数の最後のリンクを指定します.
  • リンクスクリプトで使用されるSection名は、実は変数の形式であり、定義する必要はなく、直接使用することができます.つまり、接続スクリプトでセグメント名
  • を自由に使用することができます.
  • デフォルトでsection属性が指定する場合、初期化されていれば格納.dataセグメント;さもないと預けます.bssセグメント.sectionプロパティを指定すると、初期化するかどうかにかかわらず、指定したセグメントが格納されます.
  • //__init
    #define __init __attribute__ ((__section__ (".init.text"))) __cold
    //__initdata
    #define __initdata __attribute__ (( __section__ (".init.data")))
    //__exitdata
    #define __exitdata __attribute__ (( __section__ (".exit.data")))
    
    [23] .data PROGBITS 0000000000600900 00000900
    0000000000000004 0000000000000000 WA 0 0 4
    [24] .init.data PROGBITS 0000000000600904 00000904
    0000000000000018 0000000000000000 WA 0 0 4
    [25] .bss NOBITS 0000000000600920 0000091c
    0000000000000010 0000000000000000 WA 0 0 8
    
  • noreturnの主な機能は、コンパイラに呼び出されたことを伝えるために使用されます.attribute__(noreturn)の関数の後、制御はcaller
  • に戻らない.
    void __attribute__((noreturn)) die(void);
    
  • noinline always_inline
  • inline int add(int a, int b) __attribute__((always_inline));
    inline int add(int a, int b) __attribute__((noinline));
    

    noinline:強制的にインラインしません.1つの関数は、コード量が少ない場合、-O 3最適化スイッチを使用すると、gccがこの関数を強制的にインライン(inline)する可能性があります.
    always_义齿インラインと定義してもすべてインラインされるとは限らないので、インラインは最後にgccコンパイラによって決定されます.
  • pure pureは、関数が戻り値を除いて、他の(例えばグローバル変数、ポインタ)によって関数の外部に影響を及ぼさないことを示す.const
  • と同様
    #define __purefunc    __attribute__((pure))
    int    memcmp(const void *, const void *, size_t) __purefunc;
    extern int atoi(const char*) __purefunc
    

    パラメータが同じ場合、コンパイラは最適化され、キャッシュがパラメータとして使用される可能性があります.
    char *x = calloc(1, 8);
    char *y = calloc(1, 8);
    
    if (memcmp(x, y, 8) > 0)
        printf("x > y
    "
    ); // , , 。 x[1] = 'a'; if (memcmp(x, y, 8) > 0) printf("x > y
    "
    );
  • const定数最適化const attributeはコンパイラに最適化させる.const関数はより厳密です_pure関数
  • 入力パラメータは定数であり、戻り値は同じであるため、複数回呼び出すときにコンパイラが最適化し、
  • を1回実行する.
  • pure/const関数は読むしかなく、書くことができず、printなどをすることができません.
  • for(int i = 0; i < fibonacci(100); ++i)
    {
        ...
    }for(int i = 0,end = fibonacci(100); i < end; ++i)
    {
        ...
    }
    
    //     
    int output() __attribute__((const));
     
    int output()
    {
        std::cout << "lol | ";
        return 1;
    }
    
  • constructor/destructor main関数の前後で
  • を実行
    関数がconstructorプロパティに設定されている場合、main()関数が実行される前に自動的に実行されます.同様に、関数がdestructorプロパティに設定されている場合、main()関数の実行後またはexit()が呼び出された後に自動的に実行されます.
    __attribute__((constructor)) void before_main() {
       printf("--- %s
    "
    , __func__); } __attribute__((destructor)) void after_main() { printf("--- %s
    "
    , __func__); }
  • format検査パラメータ
  • attribute((format(printf,m,n))attribute((format(scanf,m,n))format属性はコンパイラに教え、printf,scanf,strftimeまたはstrfmonのパラメータテーブルフォーマット規則に従って関数のパラメータを検査する
    m:いくつかのパラメータはフォーマット文字列(format string);n:パラメータセットの最初のパラメータ、すなわちパラメータ「...」の最初のパラメータは、関数パラメータの総数で何番目に並んでいますか.
    //m=2;n=3
    extern void myprint(int l,const char *format,...) __attribute__((format(printf,2,3)));
    

    ゼロ長配列
    役割:小さな内蔵を防止するには、構造体に長さの動的な文字列を格納する必要があります.たとえば、構造体に名前を格納しますが、この名前の長さは不明です.
    #include 
    #include 
    #include 
    
    struct node{
        int num;
        int data;
        char name[0];  //                [0]   
    };
    
    char test_name[] = "testname";
    
    int main(void)
    {
        struct node *test_node;
        int length = strlen(test_name);
        //     malloc()
        test_node = (struct node*)malloc(sizeof(struct node)+length);
        //strncpy((char *)test_node+1, test_name, length);
        strncpy(test_node->name, test_name, length);
    
        printf("sizeof(struct node) = %d
    "
    , sizeof(struct node)); printf("num addr:%p
    "
    , &(test_node->num)); printf("data addr:%p
    "
    , &(test_node->data)); printf("name addr:%p
    "
    , test_node->name); printf("test_node+1 addr:%p
    "
    , test_node+1); printf("name = %s
    "
    , test_node->name); printf("name[0] = %c
    "
    , test_node->name[0]); printf("name[%d] = %c
    "
    , lenght-1, test_node->name[length-1]); free(test_node); }
    //result
    sizeof(struct node) = 8
    num addr:0x1574010
    data addr:0x1574014
    name addr:0x1574018
    test_node+1 addr:0x1574018
    name = testname
    name[0] = t
    name[7] = e
    

    ぶんしき
    括弧でのループ、ローカル変数などの使用
    #define min_t(type,x,y) \   
    ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })   
      
    int ia, ib, mini;   
    float fa, fb, minf;   
      
    //     __x   __y        ,                 。  
    mini = min_t(int, ia, ib);   
    minf = min_t(float, fa, fb);   
    
    

    標準Cでは、次のマクロに対応して副作用が発生します.
     #define min(x,y) ((x) < (y) ? (x) : (y))    min(++ia,++ib)     ((++ia) < (++ib) ? (++ia): (++ib)),           。
    

    typeof取得タイプ
    typeof(x)文はxのタイプを得ることができる
    #define min(x,y) ({ \   
    const typeof(x) _x = (x); \   
    const typeof(y) _y = (y); \   
    (void) (&_x == &_y); \   
    _x < _y ? _x : _y; })   
    

    チェックの種類
    (void) (&_x == &_y)
    

    チェック_xと_yのタイプが一致しているかどうか、2つの異なるポインタタイプが比較操作を行うと、コンパイラにコンパイル警告が発生し、この2つの値のタイプが異なることを示します.
    範囲拡張switch...case...と配列
  • switch …case…
  • static int sd_major(int major_idx)
    {
        switch (major_idx) {
        case 0:
            return SCSI_DISK0_MAJOR;
        case 1 ... 7:
            return SCSI_DISK1_MAJOR + major_idx - 1;
        case 8 ... 15:
            return SCSI_DISK8_MAJOR + major_idx - 8;
        default:
            BUG();
            return 0;   /* shut up gcc */
        }
    }
    
  • 配列
  • /* Vector of locks used for various atomic operations */
    spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
    int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
    

    __ビルディング関数
  • 判断呼び出しアドレス_builtin_return_address
  • __builtin_return_address (LEVEL)   //LEVEL      
    

    現在の関数または呼び出し元の戻りアドレスを返します.パラメータLEVELは、0が現在の関数の戻りアドレス、1が現在の関数の呼び出し元の戻りアドレスなどの呼び出しスタックの段数を指定します.
  • コンパイル定数検出_builtin_constant_p(EXP)は、1つの値がコンパイル時定数であるか否かを判断し、パラメータEXPの値が定数である場合、関数は1を返し、そうでない場合は0を返す.
  • #define roundup_pow_of_two(n)           \
    (                       \
        __builtin_constant_p(n) ? (     \
            (n == 1) ? 1 :          \
            (1UL << (ilog2((n) - 1) + 1)) \
                       ) :      \
        __roundup_pow_of_two(n)         \
    )
    
  • ブランチ予測プロンプトのコンパイル_builtin_expect(EXP,C)は、コンパイラに分岐予測情報を提供するために使用され、その戻り値は整数式EXPの値であり、Cの値はコンパイル時定数でなければならない.
  • //  if  
    #define likely(x)   __builtin_expect(!!(x), 1)   //  if          
    #define unlikely(x) __builtin_expect(!!(x), 0)   //  else          
    if (likely(a>b)) {
      fun1();
    }
    
    

    可能性が高いのは前に置く