未使用__attribute__
最も簡単な属性の1つは、変数として、このマークを使用するように 意図的に 可能性が未使用であること。だけでなく、未使用の変数の警告を発行するから、コンパイラは、それが人間に同じことを伝え、この静かな:これは意図的なものです。
もちろん、それは実際にあなたが使用していないという変数を削除することをお勧めします、これは常に可能ではありません。主に未使用のint ARGCパラメータ()の一般的なケースは時々条件コンパイルによって除外変数である、ものです。
int main(int argc, char **argv)
{
/* code that uses argv, but not argc */
}
$ gcc -W test.c
test.c:1: warning: unused parameter 'argc'
__attribute__は、単に変数名の後に追加され、それは扱いにくい現れることができますが、それはあなたがに慣れることができたスタイルですされています。
int main(int argc __attribute__((unused)), char **argv)
{ ...
追加の用途は、それが生成されている場合がありますコンパイラの警告を示すコメントでそれぞれを示します。ここでは、コードがコンパイルされると仮定 することなく、デバッグ マクロが定義されている除外mypidの実際の使用。
/* warning: 'someFunction' declared 'static' but never defined */
static int someFunction() __attribute__((unused));
int main(int argc __attribute__((unused)), char **argv)
{
/* warning: unused variable 'mypid' */
int mypid __attribute__((unused)) = getpid();
#ifdef DEBUG
printf("My PID = %d\n", mypid);
#endif
return 0;
}
__attribute__フォーマット
この __attribute__は、 割り当て可能 printfの様または scanfの宣言された関数の特性様に、これは、コード全体で提供されたパラメータに対する書式文字列を確認するようにコンパイラを可能にします。これは、 非常に 見つけにくいバグを追跡するのに役立ちます。
2つの種類があります。
- __attribute __((形式(printf関数、M、N)))
- __attribute __((形式(scanf関数、M、N)))
しかし実際には、我々ははるかに多くの場合、最初のものを使用します。
(mは)「フォーマットストリング」パラメータの数であり、(N)第一の可変引数のパラメータの数です。いくつかの例を表示するには:
/* like printf() but to standard error only */
extern void eprintf(const char *format, ...)
__attribute__((format(printf, 1, 2))); /* 1=format 2=params */
/* printf only if debugging is at the desired level */
extern void dprintf(int dlevel, const char *format, ...)
__attribute__((format(printf, 2, 3))); /* 2=format 3=params */
そう宣言された関数を使用すると、コンパイラは、引数リストを調べます
$ cat test.c
1 extern void eprintf(const char *format, ...)
2 __attribute__((format(printf, 1, 2)));
3
4 void foo()
5 {
6 eprintf("s=%s\n", 5); /* error on this line */
7
8 eprintf("n=%d,%d,%d\n", 1, 2); /* error on this line */
9 }
$ cc -Wall -c test.c
test.c: In function `foo':
test.c:6: warning: format argument is not a pointer (arg 2)
test.c:8: warning: too few arguments for format
printf関数など - - すでにデフォルトでは、コンパイラによって理解されている「標準」ライブラリ関数があることに注意してください。
__attribute__ noreturn
この属性は、関数は、これまで戻らないということをコンパイラに伝え、これが到達していないコードパスについての抑制のエラーに使用することができます。Cライブラリの関数は(中止)とexit()は両方とも、この属性で宣言されています。
extern void exit(int) __attribute__((noreturn));
extern void abort(void) __attribute__((noreturn));
一度このようにタグ付けされ、コンパイラはこれまでに、関数呼び出しの後に戻ったことがないコントロールの流れに起因する発生しませんコードと抑制のエラーを通じてパスを追跡することができます。
この例では、2つのほぼ同一Cソースファイルは決して戻って、しかしなしていること「exitnow()」関数を参照 __attribute__ タグ、コンパイラの警告を発します。それは制御が戻らないことを知る方法がないため、コンパイラは、ここに正しいです。
$ cat test1.c
extern void exitnow();
int foo(int n)
{
if ( n > 0 )
{
exitnow();
/* control never reaches this point */
}
else
return 0;
}
$ cc -c -Wall test1.c
test1.c: In function `foo':
test1.c:9: warning: this function may return with or without a value
私たちが追加したときしかし __attribute__を、コンパイラは偽の警告を抑制します。
$ cat test2.c
extern void exitnow() __attribute__((noreturn));
int foo(int n)
{
if ( n > 0 )
exitnow();
else
return 0;
}
$ cc -c -Wall test2.c
no warnings!