2016-05-01 14 views
20

私はこのCのコード例を見つけて、私は絶対に困惑しています:C奇妙なマクロ構文

#include <stdio.h> 
#define M(a,b) a%:%:b 

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", M(a,b)<:a:>); 
    printf("%d", M(a,b)<:a:>?a:b); 
    printf("%d", c=M(a,b)<:a:>?a:b); 
} 

誰かがこれを行うことになっているかを説明できますか?それはVisual Studioでもコンパイルされませんが、オンラインで(ideone.comに)実行し、それは2011と表示され、これも混乱の原因となります。

+2

の可能性のある重複して20aで、彼らの実際の値で、すなわちab[a]を変数に置き換える[Cを何??!??!演算子は?](http://stackoverflow.com/questions/7825055/what-does-the-c-operator-do) – GSerg

+4

これは難読化されたCコンテストからですか? –

+0

は説明できません、また前に見たことがありません。これはosx/darwin/unixでコンパイルされます。 FYI、第1行は「20」、第2行「1」、第3行「1」を評価して印刷する。 – user3078414

答えて

37

これは、1994年のC標準の改訂版であり、したがってC99標準の一部であったC digraphsを使用しています。彼らの実際の文字と二重字をスワップアウト、あなたが得る:

#include <stdio.h> 
#define M(a,b) a##b 

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", M(a,b)[a]); 
    printf("%d", M(a,b)[a]?a:b); 
    printf("%d", c=M(a,b)[a]?a:b); 
} 

ので、a##bは、単一の識別子への入力を一緒にマージされることに注意してください。マクロはちょうどabを渡されているので、あなたが効果的に持っているので、結果は、ちょうどabです:

main() 
{ 
    int a=1, b=2, ab[]={10,20}, c; 
    printf("%d", ab[a]); 
    printf("%d", ab[a]?a:b); 
    printf("%d", c=ab[a]?a:b); 
} 

cへの割り当ては、実際には関係ありませんので、我々はそれを取り除くことができます。

main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", ab[a]); 
    printf("%d", ab[a]?a:b); 
    printf("%d", ab[a]?a:b); 
} 

は今、私たちは静的にそれをうまくすることができますので、のは、三項演算子(?:)を取り除くみましょう(aは1とab[1]が20であるため、ab[a]は常に真である、すなわち、非ゼロ):

main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", ab[a]); 
    printf("%d", a); 
    printf("%d", a); 
} 

1

main() 
{ 
    int a=1, b=2, ab[]={10,20}; 
    printf("%d", 20); 
    printf("%d", 1); 
    printf("%d", 1); 
} 
+7

印象的な分析 –

+3

うわー、これはまったく新しい可能性の世界を開きます。 :Dありがとう! – Eutherpy

+58

@Eutherpy:いいえいいえ。あなたはそれを見たことのないふりをする。 –