Skip to content

Instantly share code, notes, and snippets.

@ryochack
Created May 20, 2014 18:06
Show Gist options
  • Select an option

  • Save ryochack/ae7d32fa328ee3084800 to your computer and use it in GitHub Desktop.

Select an option

Save ryochack/ae7d32fa328ee3084800 to your computer and use it in GitHub Desktop.
externの配列定義を使ったビルド時の配列サイズチェック方法 (MINIX3より)
#define RESOURCE_NUM (8)
#define ARRAY_NUM (8)
struct resource {
int id;
unsigned int addr;
int len;
};
struct resource rscs[] = {
{ 0, 0x10, 4 },
{ 1, 0x14, 2 },
{ 2, 0x16, 2 },
{ 3, 0x18, 4 },
{ 4, 0x20, 1 },
{ 5, 0x21, 1 },
{ 6, 0x22, 2 },
{ 7, 0x24, 4 },
};
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
extern int dummy[(RESOURCE_NUM == sizeof(rscs)/sizeof(rscs[0])) ? 1 : -1];
extern int dummy[(ARRAY_NUM == sizeof(array)/sizeof(array[0])) ? 1 : -1];
@ryochack

Copy link
Copy Markdown
Author

配列のサイズが想定と異なるときには、extern int dummy[]のところで要素数が-1になりビルドエラーになる。
dummyはextern宣言なので実体は確保されない。

@ryochack

ryochack commented Aug 16, 2017

Copy link
Copy Markdown
Author

NordicのSDKでは以下の方法(STATIC_ASSERT(EXPR))でStatic checkをしている。
固定でゼロ除算をしてエラーを起こしている。

/**@brief Implementation specific macro for delayed macro expansion used in string concatenation
 * @param[in]   lhs   Left hand side in concatenation
 * @param[in]   rhs   Right hand side in concatenation
 */
#define STRING_CONCATENATE_IMPL(lhs, rhs) lhs ## rhs

/**@brief Macro used to concatenate string using delayed macro expansion
 * @note This macro will delay concatenation until the expressions have been resolved
 * @param[in]   lhs   Left hand side in concatenation
 * @param[in]   rhs   Right hand side in concatenation
 */
#define STRING_CONCATENATE(lhs, rhs) STRING_CONCATENATE_IMPL(lhs, rhs)

/**@brief Macro for doing static (i.e. compile time) assertion.
 * @note If the EXPR isn't resolvable, then the error message won't be shown.
 * @note The output of STATIC_ASSERT_MSG will be different across different compilers.
 * @param[in] EXPR Constant expression to be verified.
 */
#define STATIC_ASSERT(EXPR) \
    ;enum { STRING_CONCATENATE(assert_line_, __LINE__) = 1/(!!(EXPR)) }

STRING_CONCATENATE(assert_line_, __LINE__)しているのは、enumの要素名を変えて定義がバッティングしないようにするため。

@ryochack

Copy link
Copy Markdown
Author

MINIX3の方をマクロ化。

#define STATIC_ASSERT2(EXPR) \
    ;extern int STRING_CONCATENATE(assert_line_, __LINE__)[(!!(EXPR)) ? 1 : -1]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment