コグノスケ


link 未来から過去へ表示(*)  link 過去から未来へ表示

link もっと前
2020年5月4日 >>> 2020年5月4日
link もっと後

2020年5月4日

C言語のマクロ

目次: C言語とlibc

C言語のマクロによる置換を、循環参照させたらどうなるでしょう?

循環するマクロ定義

A B C D
#define A B
A B C D
#define B C
A B C D
#define C A
A B C D

結論から言うと問題ありません。下記のような結果になります。

循環するマクロ定義、置換結果

A B C D

B B C D

C C C D

A B C D

4つ目の結果は、置換前のA B C Dと何も変わっていないように見えますが、実はそうではありません。下記のように定義するとわかります。

循環するマクロ定義、マクロによる置換結果を見やすくする

A B C D
#define A 1 B
A B C D 
#define B 2 C
A B C D 
#define C 3 A
A B C D
循環するマクロ定義、置換結果が見やすいはず

A B C D

1 B B C D

1 2 C 2 C C D

1 2 3 A 2 3 1 B 3 1 2 C D

4つ目の結果の「A」を例にとると、A -> B -> C -> Aと3回のマクロの置換が行われた結果、Aに戻っているわけです。#define A Bのマクロは1度しか適用されないようです。

C言語の仕様

C言語の仕様(C11 final draft (N1570) - 6.10.3.4 Rescanning and further replacementの第2項)を見ると、

2
If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file's preprocessing tokens), it is not replaced. Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced. These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

(直訳)
2
置換されるマクロの名前がreplacement listのスキャン中に見つかった場合(ソースファイルの残りの前処理トークンは含まれません)、そのマクロは置換されません。 さらに、入れ子になった置換が、置換されているマクロの名前に遭遇した場合、それは置換されません。 後にそのマクロ名の前処理トークンが置換されていたであろうコンテキストで(再)検査されても、これらの置換されていないマクロ名の前処理トークンはそれ以上の置換はできなくなります。

正直言って何言ってんだお前……?って感じがしますけども、平たく言うと同じマクロを2回適用しない、ように読めます。

複雑版

下記のように同じマクロで何度も置換できそうなマクロを定義してみます。

循環するマクロ定義、より複雑版

#define A B C
#define B C A
#define C A B
A B C D
循環するマクロ定義、より複雑版、結果

A B A A C A B C B B A B C A C C B C D

1つ1つのトークンがどのマクロで展開されているか図示します。


循環するマクロ定義、展開の様子

複雑に見えますが、どのトークンを見ても同じマクロを2回適用されたものはないことがわかります。

関数型マクロの謎

しかし関数型マクロの場合は、不思議な挙動を示します。

循環する関数型マクロ定義

#define F(a) a G
#define G(a) a F(a)

F(7)(8)(9)
循環する関数型マクロ定義、結果


7 8 8 G(9)

展開の様子は下記のようになると思われますが、


循環する関数マクロ定義、展開の様子

どうして7 8 8 G(9) で展開が終わるのかが良くわかりません……。マクロF(a) を2回適用しない、というルールならば、7 8 F(8)(9) で止まらなければおかしいように思いますが、結果を見るとなぜかF(8) も展開されています。

編集者:すずき(2023/02/04 20:17)

コメント一覧

  • コメントはありません。
open/close この記事にコメントする



link もっと前
2020年5月4日 >>> 2020年5月4日
link もっと後

管理用メニュー

link 記事を新規作成

<2020>
<<<05>>>
-----12
3456789
10111213141516
17181920212223
24252627282930
31------

最近のコメント5件

  • link 24年4月22日
    hdkさん (04/24 08:36)
    「うちのHHFZ4310は15年突破しまし...」
  • link 24年4月22日
    すずきさん (04/24 00:37)
    「ちゃんと数えてないですけど蛍光管が10年...」
  • link 24年4月22日
    hdkさん (04/23 20:52)
    「おお... うちのHHFZ4310より後...」
  • link 20年6月19日
    すずきさん (04/06 22:54)
    「ディレクトリを予め作成しておけば良いです...」
  • link 20年6月19日
    斎藤さん (04/06 16:25)
    「「Preferencesというメニューか...」

最近の記事3件

  • link 24年4月25日
    すずき (04/26 16:49)
    「[AVIFの変換] AVIFが読めないアプリケーションがたまにあるので、AVIF(AV1 Image File Format)...」
  • link 24年2月7日
    すずき (04/24 02:52)
    「[複数の音声ファイルのラウドネスを統一したい] PCやデジタル音楽プレーヤーで音楽を聞いていると、曲によって音量の大小が激しく...」
  • link 24年4月22日
    すずき (04/23 20:13)
    「[仕事部屋の照明が壊れた] いきなり仕事部屋のシーリングライトが消えました。蛍光管の寿命にしては去年(2022年10月19日の...」
link もっとみる

こんてんつ

open/close wiki
open/close Linux JM
open/close Java API

過去の日記

open/close 2002年
open/close 2003年
open/close 2004年
open/close 2005年
open/close 2006年
open/close 2007年
open/close 2008年
open/close 2009年
open/close 2010年
open/close 2011年
open/close 2012年
open/close 2013年
open/close 2014年
open/close 2015年
open/close 2016年
open/close 2017年
open/close 2018年
open/close 2019年
open/close 2020年
open/close 2021年
open/close 2022年
open/close 2023年
open/close 2024年
open/close 過去日記について

その他の情報

open/close アクセス統計
open/close サーバ一覧
open/close サイトの情報

合計:  counter total
本日:  counter today

link About www.katsuster.net
RDFファイル RSS 1.0

最終更新: 04/26 16:49