2013年1月20日日曜日
2012年8月4日土曜日
2012年6月19日火曜日
マクロを文字列化する
プリプロセッサでマクロを文字列化する方法ないかな〜、って以前から思ってたんですが、 u-boot のソースコード読んでいたときに発見しました!
どういうことかといいますと #x のような文字列化機能がプリプロセッサにありますね。
例えば、以下のような感じ。
---
#include <stdio.h>
#define MK_STR(x) #x
char buf[] = "baudrate=" MK_STR(19200);
int main()
{
puts(buf);
return 0;
}
---
これをコンパイル、実行すると
19200 → "19200" のように文字列化してくれています。ここまで普通です。
やりたいことは、19200 の部分をマクロで定義しておきたいのです。
---
#include <stdio.h>
#define CONFIG_BAUDRATE 19200
#define MK_STR(x) #x
char buf[] = "baudrate=" MK_STR(CONFIG_BAUDRATE);
int main()
{
puts(buf);
return 0;
}
---
う〜ん、残念。
CONFIG_BUADRATE → 19200 → "19200"
と置き換えてほしいんですが、 CONFIG_BAUDRATE をそのまま文字列化してくれました。
sprintf(buf, "%d", CONFIG_BAUDRATE)
みたいに sprintf は使いたくない。
で、今回見つけたやり方は以下の方法。
---
#include <stdio.h>
#define CONFIG_BAUDRATE 19200
#define XMK_STR(x) #x
#define MK_STR(x) XMK_STR(x)
char buf[] = "baudrate=" MK_STR(CONFIG_BAUDRATE);
int main()
{
puts(buf);
return 0;
}
---
$ ./a.out
baudrate=19200
おぉぉ〜!うまくいった。
一見無駄にも見える
というマクロ定義ですが、こんな効能があるんですね。
どういうことかといいますと #x のような文字列化機能がプリプロセッサにありますね。
例えば、以下のような感じ。
---
#include <stdio.h>
#define MK_STR(x) #x
char buf[] = "baudrate=" MK_STR(19200);
int main()
{
puts(buf);
return 0;
}
---
これをコンパイル、実行すると
$ ./a.out
baudrate=19200
baudrate=19200
19200 → "19200" のように文字列化してくれています。ここまで普通です。
やりたいことは、19200 の部分をマクロで定義しておきたいのです。
---
#define CONFIG_BAUDRATE 19200
#define MK_STR(x) #x
char buf[] = "baudrate=" MK_STR(CONFIG_BAUDRATE);
int main()
{
puts(buf);
return 0;
}
---
$ ./a.out
baudrate=CONFIG_BAUDRATE
baudrate=CONFIG_BAUDRATE
う〜ん、残念。
CONFIG_BUADRATE → 19200 → "19200"
と置き換えてほしいんですが、 CONFIG_BAUDRATE をそのまま文字列化してくれました。
sprintf(buf, "%d", CONFIG_BAUDRATE)
みたいに sprintf は使いたくない。
で、今回見つけたやり方は以下の方法。
---
#include <stdio.h>
#define CONFIG_BAUDRATE 19200
#define XMK_STR(x) #x
#define MK_STR(x) XMK_STR(x)
char buf[] = "baudrate=" MK_STR(CONFIG_BAUDRATE);
int main()
{
puts(buf);
return 0;
}
---
$ ./a.out
baudrate=19200
おぉぉ〜!うまくいった。
一見無駄にも見える
#define XMK_STR(x) #x
#define MK_STR(x) XMK_STR(x)
#define MK_STR(x) XMK_STR(x)
というマクロ定義ですが、こんな効能があるんですね。
2012年4月6日金曜日
2012年4月5日木曜日
2012年2月24日金曜日
C言語のswitch文で ...
Linux のコードを見ていると、こんな書き方もできるのかぁ、というものに出くわすことがありますね。
例えば、
arch/arm/mach-rpc/irq.c にある、以下のようなコード。
switch (irq) {
case 0 ... 7:
irq_set_chip_and_handler(irq, &iomd_a_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 8 ... 15:
irq_set_chip_and_handler(irq, &iomd_b_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 16 ... 21:
irq_set_chip_and_handler(irq, &iomd_dma_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 64 ... 71:
irq_set_chip(irq, &iomd_fiq_chip);
set_irq_flags(irq, IRQF_VALID);
break;
}
「...」で範囲指定できるらしい。見た時びっくりしました。
例えば、
arch/arm/mach-rpc/irq.c にある、以下のようなコード。
switch (irq) {
case 0 ... 7:
irq_set_chip_and_handler(irq, &iomd_a_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 8 ... 15:
irq_set_chip_and_handler(irq, &iomd_b_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 16 ... 21:
irq_set_chip_and_handler(irq, &iomd_dma_chip,
handle_level_irq);
set_irq_flags(irq, flags);
break;
case 64 ... 71:
irq_set_chip(irq, &iomd_fiq_chip);
set_irq_flags(irq, IRQF_VALID);
break;
}
「...」で範囲指定できるらしい。見た時びっくりしました。
gcc のマニュアルを参照すると
http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
これはGNU 拡張機能らしいです。
(Case Ranges: `case 1 ... 9' and such. )
gcc に -pedantic をつけると非標準機能を使っていると警告してくれるみたい。
ポータビリティを気にする場合は便利かも。
上のような書き方をすると
警告: range expressions in switch statements are non-standard
という風に warning 出してくれました。
http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions
これはGNU 拡張機能らしいです。
(Case Ranges: `case 1 ... 9' and such. )
gcc に -pedantic をつけると非標準機能を使っていると警告してくれるみたい。
ポータビリティを気にする場合は便利かも。
上のような書き方をすると
警告: range expressions in switch statements are non-standard
という風に warning 出してくれました。
登録:
投稿 (Atom)