gnu C言語_attribute__さぎょう


attributeについて
linuxのソースコードを見ていると、dl_など、関連するものによく出会うかもしれません.Openの関数の中:
void* internal_function 
  _dl_open (const char *file, int mode, const void *caller)
  {
     struct dl_open_args args;

       __rtld_lock_lock_recursive (GL(dl_load_lock));

     args.file = file;
     args.mode = mode;
     args.caller = caller;
     args.map = NULL;

     dl_open_worker(&args);
        __rtld_lock_unlock_recursive (GL(dl_load_lock));

  }

ここのinternal_functionはattributeの応用であり、その具体的なフォーマットは以下の通りである.
#define internal_function __attribute__ ((regparm (3), stdcall))

attributeは、その名の通り、関数(変数や構造体)のいくつかの属性を説明し、コンパイラにより多くの情報を提供します.ここでは、一般的なattributeの使い方を説明します.
に注意
gnu ccは-Wallでこのオプションをアクティブにする必要があります
使用法
1フォーマット判定format
説明:すなわち、フォーマット文字列に従ってパラメータの正当性を判断し、法則コンパイラがwarningの具体的なフォーマットを与える場合:attribute(format(type,string_index,first_to_check))解釈:typeはscanfまたはprintfを記入し、scanfまたはprintfで検出することを表す.string_indexはフォーマット文字列が関数のいくつかのパラメータであることを示し、最後にfirst_to_checkは、チェックするパラメータが関数の位置にある例を示します.
void myPrint(const char* format_string, ...)
__attribute__(format(printf, 1, 2));//format_string       ,   ...        
//           ,                ,   format(printf, 1, 2)
// string_index = 1, first_to_check = 2

2関数は呼び出し元noreturnに返されません
説明:この関数は呼び出し元に戻る必要がないことを示し、不要な最適化の具体的なフォーマットを避ける:attribute(noreturn))の例:
void myExit() __attribute__((noreturn));

3 const attribute
説明:この属性は主に静的状態と副作用のない関数で使用され、その戻り値は主に入力値に依存し、数値タイプの関数のみで使用でき、ポインタタイプのパラメータを持つ関数では使用できません.具体的なフォーマット:attribute(const))の例:
void intSqrt(int x)__attribute__((const))
//  sqrt      x   ,                     ,const         
//             ,      ,         ,                 

4 no_instrument_function
説明:この属性はgccのコンパイルオプション、-finstumat-functionに関連するため、説明が複雑である.このパラメータを追加すると、コンパイル時にinstrumentation呼び出しが生成されます.すなわち、1つの関数のエントリの後と、エクスポートの前に2つの関数が呼び出されます.それぞれ:
void __cyg_profile_func_enter(void *this_fn, void *call_site);
void __cyg_profile_func_exit(void *this_fn, void *call_site);
//profile  

Instrumentation呼び出しを生成する必要がない関数は、profile関数自体、高優先度の割り込みルーチン、profilingの正常な呼び出しを保証できない関数などの典型的な使用方法で、この属性を使用して明記されます.具体的なフォーマット:attribute(no_instrument_function))の例:
//test.c
#include 
void __cyg_profile_func_enter(void *, void *)
    __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *, void *)
    __attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site)
{
    printf("this_func: %p call_addr: %p
"
, this_fn, call_site); } void __cyg_profile_func_enter(void *this_fn, void *call_site) { printf("this_func: %p call_addr: %p
"
, this_fn, call_site); } int main() { printf("hey, everybody!
"
); return 0; }

コンパイルコマンド:
gcc -o test test.c -finstrument-functions

出力結果:(64ビットシステムです)
this_func: 0x400645 call_addr: 0x7feebbbd8f45
hey, everybody!
this_func: 0x400645 call_addr: 0x7feebbbd8f45

5 constructor/destructorプロパティ
説明:主に関数の初期化などに用いられ、constructor属性が宣言されている場合はmain関数の前に実行され、destructor属性が宣言されている場合はmain関数の実行後、またはexitが呼び出されて自動的に実行されます.具体的なフォーマット:attribute(constructor)attribute(destructor)の例:
//test.c
#include 
void constructor_func()
    __attribute__((constructor));
void destructor_func()
    __attribute__((destructor));
void constructor_func()
{
    printf("I am a constructor :)
"); }
void destructor_func() { printf("I am a destructor :)
"); }
int main() { printf("I am main, I did nothing! :(
"); return 0; }

コンパイルオプション:
gcc -o test test.c

実行結果:
I am a constructor :)
I am main, I did nothing! :(
I am a destructor :)

6変数属性
説明:前に説明したすべての設定は、関数を設定します.ここでは、関数を設定するだけでなく、変数と構造体を属性設定することもできます.共通変数のプロパティ:
  • alignedは、整列フォーマット:int x[3] __attrubute__((aligned(16)))、すなわち16バイト整列を示す.(オブジェクトのスペースを増やす)
  • packed、最小整列方式を使用します.int x[3] __attribute__((packed))(オブジェクトの占有スペースを減らす)...
  • ここではリストしません.より多くの変数プロパティを参照してください.
    7タイプ属性
    説明:変数属性が変数に対する属性宣言のように、タイプ属性はタイプに対する属性宣言です.主にstructとunionに対して属性宣言を行い、ここでは後述しないが、第6点と比較して類似しており、より多くのタイプの属性はこれを参照してください.
    tips
  • attributeのプロパティは、マクロの重複を回避するために、前後に二重下線を付けることができます.
  • は、__attrubute__((noreturn, format(printf, 1, 2)))のような複数の属性を1つのattributeで示すことができ、__attribute__((noreturn)) __attribute__((format(printf, 1, 2)))
  • のような複数のattributeを書くこともできる.