第9章:コンパイラ拡張と標準適合
この章で学ぶこと
- GCC/Clangの主要な拡張
- __attribute__ の活用
- コンパイラオプションと標準モード
- 拡張を使わない移植可能なコード
__attribute__typeof(C23で標準化)- Statement expressions
- Nested functions(GCCのみ)
---
9.1 コンパイラ拡張とは
定義
標準規格で規定されていない機能。コンパイラ固有。
よく使われる拡張
---
9.2 GCC/Clang の __attribute__
関数属性
/* 非戻り関数 */
void die(const char *msg) __attribute__((noreturn));
/* 純粋関数(副作用なし、同じ引数で同じ結果) */
int square(int x) __attribute__((pure));
/* 定数関数(グローバル状態も参照しない) */
int add(int a, int b) __attribute__((const));
/* printf形式のチェック */
void log_msg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
/* 非推奨 */
void old_api(void) __attribute__((deprecated("use new_api instead")));
/* インライン化を強制 */
__attribute__((always_inline)) inline int fast_op(int x);
変数属性
/* アラインメント */
int data __attribute__((aligned(16)));
/* セクション指定 */
int persistent __attribute__((section(".data")));
/* 未使用警告を抑制 */
int reserved __attribute__((unused));
型属性
/* パックド構造体(パディングなし) */
struct __attribute__((packed)) packet {
uint8_t type;
uint32_t data;
};
---
9.3 C23での標準化
属性構文
/* C23標準属性 */
[[noreturn]] void die(const char *msg);
[[deprecated("use new_api")]] void old_api(void);
[[maybe_unused]] int reserved;
[[nodiscard]] int important_func(void);
typeof
/* C23で標準化 */
int x = 42;
typeof(x) y = x; /* int y = x; と同等 */
typeof_unqual(const int) z; /* int z; */
---
9.4 標準モードの指定
GCC/Clang オプション
# 標準モード
gcc -std=c89 file.c
gcc -std=c99 file.c
gcc -std=c11 file.c
gcc -std=c17 file.c
gcc -std=c23 file.c
# GNU拡張付き(デフォルト)
gcc -std=gnu11 file.c
# 厳格な標準適合
gcc -std=c11 -pedantic file.c
gcc -std=c11 -pedantic-errors file.c
拡張の検出
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* GCC拡張が利用可能 */
#endif
#if __STDC_VERSION__ >= 201112L
/* C11以降 */
#endif
#if __STDC_VERSION__ >= 202311L
/* C23以降 */
#endif
---
9.5 移植可能なコード
属性のラッパー
#if defined(__GNUC__) || defined(__clang__)
#define NORETURN __attribute__((noreturn))
#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
#elif defined(_MSC_VER)
#define NORETURN __declspec(noreturn)
#define PRINTF_LIKE(f, a)
#else
#define NORETURN
#define PRINTF_LIKE(f, a)
#endif
C23対応
#if __STDC_VERSION__ >= 202311L
#define NODISCARD [[nodiscard]]
#elif defined(__GNUC__)
#define NODISCARD __attribute__((warn_unused_result))
#else
#define NODISCARD
#endif
---
9.6 Statement Expressions(GCC拡張)
/* 複合文を式として使用 */
#define max(a, b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
_a > _b ? _a : _b; \
})
int m = max(x++, y++); /* x++, y++ は一度だけ評価 */
注意: GCC/Clang固有。移植性なし。
---
9.7 この章のまとめ
GCC/Clang拡張
__attribute__((noreturn)), __attribute__((format))typeof(C23で標準化)標準適合
-std=cXX -pedantic で厳格モード---
確認問題
問題1
-pedantic オプションの効果は?
解答
標準規格で規定されていない拡張を使用した場合に警告を発する。-pedantic-errors ではエラーになる。
問題2
__attribute__((pure)) と __attribute__((const)) の違いは?
解答
pure: 副作用なし、同じ引数で同じ結果を返す(グローバル変数の読み取りは許可)const: より厳しい。グローバル状態も参照しない。
---
次の章では、C23と将来の展望について学びます。