蚀語CおよびC ++の拡匵。 パヌト1

この蚘事および䞀連の蚘事が期埅されるこずは、ほがすべおのコンパむラヌに存圚するCおよびC ++蚀語の非暙準の拡匵機胜に぀いお説明しおいたす。

蚀語拡匵機胜は、暙準の䞀郚ではない远加の機胜および蚀語の機胜ですが、コンパむラヌによっおサポヌトされおいたす。 これらの拡匵機胜の調査は非垞に興味深いです-䞻にれロから発生したものではないためです。 各拡匵機胜は、倚数のプログラマが緊急に必芁な結果です。 そしお、私は二重に興味がありたす-私はプログラミング蚀語が奜きで、自分で開発しおいるため、倚くの堎合、私のアむデアの倚くは蚀語拡匵機胜で実装されおいたす。 CおよびC ++蚀語暙準は非垞にゆっくりず開発されおおり、拡匵機胜の説明を読んで、「うヌん、これは明らかです なぜこれがただ芏栌にないのですか」

蚀語拡匵機胜は、このような「灰色」の圱の領域であり、通垞はほずんど蚘述せず、ほずんど知識がありたせん。 しかし、これはたさに圌女を面癜くするものです

汎甚コンパむラヌgcc、msvs、clang、intel、embarcadero、iarおよびkeilマむクロコントロヌラヌ甚のコンパむラヌ、そしお可胜であれば他の倚くのコンパむラヌを怜蚎するこずを事前に蚀うこずができたす。 GCCのほずんどの拡匵機胜は驚くこずではありたせん。無料の開発はさたざたな蚀語機胜の実装に貢献したす。 さらに、GCC拡匵機胜に関する情報はすべお1か所で収集され、他のコンパむラに関する情報は少しず぀収集する必芁がありたす。 それでは、GCCから始めたしょう。

C蚀語拡匵


匏ずしおの制埡ステヌトメントずコヌドブロック


最も明癜なアむデアであり、珟代のハむブリッド呜什機胜蚀語で力ず䞻に適甚されたす。 コヌドブロックは、匏の倀である堎合がありたす。 倀は、このコヌドブロックの最埌の匏の倀です。

int q = 100 + ({ int y = foo (); int z; if (y > 0) z = y; else z = - y; z; }); 

ロヌカルタグ


goto挔算子に䜿甚されるラベルには、デフォルトで機胜によっお制限されるスコヌプがありたす。 時には-たずえばマクロを展開する堎合-これは安党ではなく、ラベルの範囲を珟圚のコヌドブロックに制限するこずをお勧めしたす。 このようなラベルには、 __label__キヌワヌドを䜿甚した事前の宣蚀が必芁です。 ラベル自䜓は通垞の方法で宣蚀されたすが、そのスコヌプはブロックであり、関数ではありたせん。

倀ずしおのラベル


goto挔算子に関連する別の興味深い匷力な䜎レベル機胜は、倀ずしおラベルを䜿甚するこずです。 実際、この機胜は、ラベルがコヌド内の単なるアドレスであるアセンブラヌにも存圚したす。 しかし、GCCは特別なラベルタむプを拒吊し、ラベルをvoid *タむプに倉換する目的で、䜕らかの理由で単項挔算子&&が導入されたした。 それはずおも玠敵でハッキヌに芋えたす

 static void *array[] = { &&foo, &&bar, &&hack }; goto *array[i]; 

Dijkstraのファむリングでは、goto挔算子はほずんどのプログラマヌに奜たれたせん。 倚くの堎合、これは本圓に正圓化されたすが、Cがハッカヌ蚀語であるこずを忘れないでください。぀たり、制限よりも機䌚を奜むずいうむデオロギヌを持っおいるずいうこずです。 たた、特定の堎所オペレヌティングシステムのカヌネルなどでgotoが必芁な堎合は、アセンブラを挿入するよりもgotoを䜿甚するこずをお勧めしたす。 そしお、コヌドを台無しにしたり刀読䞍胜にしたりする方法は非垞に倚くありたすが、䞭でもgotoは最初からは皋遠いものです。

入れ子関数


C ++のLambda関数は、C ++ 11でのみ登堎したした。 䞀方、Turbo Pascalでも、1぀の機胜を別の機胜に投資するこずができたした。 C ++ずクラスの出珟により、䜕も倉わっおいたせん-クラスを関数や他のクラスにネストするこずはできたしたが、関数をネストするこずはただ蚱可されおいたせんでした。 GCCは蚀語のこの厄介な非察称性を修正したす。

入れ子関数は、倉数の受け入れぞのアクセスをサポヌトしたすが、C ++ラムダずは異なり、「クロヌゞャ」の明瀺的な指瀺を必芁ずしたせん。たた、高レベル蚀語のラムダずは異なり、自動的にそのような「クロヌゞャ」を線成したせん。 別の興味深い機胜は、ネストされた関数から埋め蟌み関数に移動するこずです。 これは、䟋倖をスロヌするタむプに䌌おいたす。

可倉数の匕数を持぀呌び出しを別の関数にリダむレクトする


関数ぞの可倉数の匕数を可倉数の匕数を持぀別の関数に転送するように蚭蚈された特別な蚀語構成䜓、および匕数の数に関する情報は必芁ありたせん。 ご存じのずおり、マクロva_start、va_arg、va_end、およびタむプva_listは、Cで可倉数の匕数を凊理する暙準的な方法です。 この方法は、Cの関数の匕数が逆の順序でスタックに曞き蟌たれ、これらのマクロが単にスタックメモリぞのアクセスを提䟛するずいう事実に基づいおいたす。 しかし、この拡匵機胜では、明らかに新しいこずがわかりたす。 これは䜕

void * __builtin_apply_args -関数はスタックにメモリを割り圓お、呌び出し元の関数の匕数をそこにコピヌしたす。

void * __builtin_applyvoid* function、void * arguments、size_t size -関数は__builtin_apply_argsを䜿甚しお䜜成されたデヌタブロック、関数ぞのポむンタヌ、およびそのスタックのサむズを受け入れたす。 関数呌び出しの内郚では、枡された匕数で圢成されたす。 関数から返された戻り倀を栌玍するスタック䞊のデヌタブロックを返したす。

void __builtin_returnvoid * result -関数は通垞の戻り倀を眮き換え぀たり、このビルドむンの埌、コヌドは実行されなくなりたす、結果にパックされた関数の結果を返したす。

したがっお、メカニズムは基本的にva_listずは異なり、vバヌゞョン぀たり、vprintfなどのva_listを受け入れるバヌゞョンを持たない可倉数の匕数を持぀関数がある堎合に適甚できたす。

しばらくの間、むンラむン関数でのみ䜿甚される2぀の組み蟌み関数がありたす。これらは垞に厳密にむンラむン化されたす通垞のむンラむン関数のようにコンパむラを蚈算するためではありたせん。

__builtin_va_arg_packは、名前のない匕数のリスト党䜓を衚したす。 このビルトむンは、可倉長匕数リストの代わりに盎接䜿甚されたす。
__builtin_va_arg_pack_lenは、名前のない匕数の数を返したす。

むンラむンバむンディングの芁件から掚枬できるように、これらの組み蟌み関数はコンパむル段階でより倚く動䜜し、スタックでの操䜜などはありたせん。 実行時に実行されたせん。

Typeof挔算子


コンパむル段階の挔算子は、匏のタむプを返したす。 同様のdecltype挔算子がC ++に登堎したのはそれほど前ではありたせん。 ただし、C ++ではなくSI拡匵機胜を怜蚎しおいるこずを思い出しおください。 もちろん、gcc c ++でも利甚可胜です

短瞮された条件挔算子


匏

 x ? x : y 

以䞋に枛らすこずができたす。

 x ? : y 

これは、特にx自䜓が長い匏である堎合に䟿利な衚蚘法です。 ちなみに、この圢匏ぱルビス挔算子ず呌ばれ、 ゚ルビス挔算子が最初のオペランドをブヌルにキャストし、それを停ず比范するずいう点でNull Coalescing_operator たずえばCに存圚ずは異なり、 ヌル合䜓はオペランドを厳密に特別なNULL倀ず比范したす。

__Int128およびlong long型


128ビットおよび64ビット敎数のもう1぀の明らかな拡匵。 long long型は、CずC ++の䞡方で暙準化されおいたすが、128ビット数の暙準はただありたせん。 それがどうなるのか、それから䜕ず呌ばれるのだろうか long long longずunsigned long long long

耇雑な


蚀語レベルでのあらゆるタむプの耇玠数のサポヌト。 そのような型を蚀語に導入するこずが理にかなっおいるずは思いたせんが、これはsiであり、ネむティブオブゞェクト、コンストラクタヌ、テンプレヌトなどはないこずを思い出しおみたしょうしかし実際にはテンプレヌト型です。 この蚀語では、接尟蟞 'i'および 'j'これは同じこずです、__ real__および__imag__挔算子、および䞀連の補助関数のサポヌトが導入されたした。

十分に深い蚀語サポヌトにより、蚀語に䜕を含めるべきかを考えるこずができるため、コンパむラヌに盎接埋め蟌むこずなく、このような特殊な型を快適に実装および䜿甚できたす。

浮動小数点型、半粟床


远加の浮動小数点型__float80、__ float128、__ fp16。
実際、 IEEE 754暙準を開くず、よく知られおいるfloatずdouble他の誰かが芚えおいる堎合はlong doubleよりも少し倚くの型があるこずがわかりたす。

10進浮動小数点数


浮動小数点数のもう1぀の興味深い圢匏は、2ではなく10に基づいおいたす䞊蚘のリンクを参照しおください。これらの圢匏もありたす。 堎合によっおは、叀兞的な浮動小数点数ず倍粟床は、孊䜍の内郚底が2であり、数倀のテキストレコヌドが10進数぀たり10進数であるずいう事実に関連する面癜い゚ラヌを䞎えるこずを思い出させおください。 たずえば、0.1 + 0.2= 0.3

基数10の浮動小数点数は、財務蚈算で䜿甚されたす。このような゚ラヌは蓄積されず、金銭の流出に぀ながりたせん。

六角フロヌト


これは、16進浮動小数点数を曞き蟌む方法です10進衚蚘を䜿甚するず、䞀郚の数倀を正確に曞き蟌むこずができないずいう事実にも関連しおいたす。 16進数字に䜿甚される文字「e」の代わりに、文字「p」が指数衚蚘に䜿甚されたす。 この番号0x12c0a34.f09de78p3はどうですか 私の意芋では、非垞にハッキヌです。

䞍動点


固定小数点数は、GCCのもう1぀の䟿利な拡匵機胜です。 プラットフォヌムによっおはFPUがない堎合があり、固定小数点の蚈算がより高速で䟿利な堎合がありたす。 䜎レベルでは、これらは通垞の敎数であり、カテゎリの䟡栌は䞀般に受け入れられおいるものずは異なりたす。 理論的には、敎数郚分ず小数郚分の任意の比率を解決できたしたが、GCCは_Fractおよび_Accumタむプの修食子に実装されたメむンワヌドサむズ2、4、および8バむトに特定の比率を採甚したした。 さらに、䜕らかの理由でこの機胜がすべおのコンパむラに含たれおいるわけではないため、実際にこの機胜を怜蚌するこずはできたせんでした。

別の_Sat修食子は飜和の蚈算に䜿甚されたす-これは凊理オヌバヌフロヌの特別なモヌドで、蚈算結果が特定の型の範囲に収たらない堎合、この型で可胜な最倧倀たたは最小倀が倉数に保存されたす。 粟床は倱われたすが、蚘号を介した遷移はないため、堎合によっおは望たしい堎合がありたす色、音などの凊理

名前付きアドレススペヌス


耇数のアドレス空間を持぀アヌキテクチャにずっお非垞に䟿利です。 たずえば、異なるマむクロコントロヌラヌ甚。 RAM、フラッシュ、eeprom、これらすべおがいく぀かのバンクにありたす。 そしお、アドレス空間ごずの独立したアドレス指定システム。

長さがれロの配列


構造が可倉長オブゞェクトのヘッダヌである堎合、最埌の芁玠ずしお構造で䜿甚されたす。 䜎レベルのコヌドには非垞に䟿利です。 これらの堎合、他のコンパむラで拡匵機胜が利甚できない堎合、1぀の芁玠の配列を䜜成する必芁がありたした。これは䞀般に正しくありたせん。オブゞェクトの可倉長はれロかもしれたせん。 たた、䜙分なサむズは䞍必芁なメモリ割り圓おなどに぀ながる可胜性がありたす。

空の構造


そのような構造が公匏に蚱可されおいるC ++ずは異なり、Cでは拡匵機胜です。 たた、Cでは、䜕らかの理由で1バむトであるC ++ずは異なり、サむズsizeofは実際にはれロです。

実行時に決定される配列


明らかなこず。 スタック䞊のメモリを割り圓おる関数allocaがありたす。 圌女を解攟する必芁はありたせん。 GCCは、蚀語レベルでこの方法で配列を宣蚀する機胜を远加したす。

 void foo(int n) { int arr[n]; } 

さらに、GCCでは、可倉長配列フィヌルドを持぀ネストされた構造を宣蚀できたす

 void foo (int n) { struct S { int x[n]; }; } 

たた、可倉長配列を䜿甚した関数長さは関数の匕数リストに瀺されおいたす

 void foo(int len, char data[len][len]) { /* ... */ } 

そしお、配列の埌に長さを指定したい堎合、これは可胜です GCCは、関数匕数のリストに予備倉数宣蚀甚の特別な構文を導入しおいたす。これは、他の倚くのアプリケヌションにずっお非垞に興味深い方法ですただし、これは別のトピックです。

 void foo (int len; char data[len][len], int len) { /* ... */ } 

可倉匕数マクロ


このようなマクロは、暙準のC99およびC ++ 11で登堎したした。 それらは以前にGCCに登堎したした。 暙準バヌゞョンに関連しお、いく぀かの改善もサポヌトされおいたす。 実際、可倉数のパラメヌタヌを持぀マクロは、可倉数の匕数をマクロに枡し、これらの匕数のパッケヌゞを単䞀のナニットずしお䜿甚しお、可倉数の匕数をサポヌトする他の蚀語゚ンティティ関数、他のマクロ、C ++テンプレヌト。 マクロ宣蚀では、匕数のパッケヌゞは3぀のドット「...」ずしお指定され、本䜓では識別子__VA_ARGS__ずしお指定されたす 。

拡匵機胜に぀いお説明したす。 たず、3぀のポむントず__VA_ARGS__の代わりに、3぀のポむントで宣蚀されおいるがそれらなしで䜿甚される通垞の名前を䜿甚できたす。 これにより、コヌドの可読性が向䞊し、䞀般的にそれ自䜓が非垞に矎しいアむデアになりたす。

 #define LOG(args...) fprintf (stderr, args) 

2番目は、「最埌のコンマ」を䜿甚した正しい䜜業です。 コヌド生成およびマクロはコヌド生成でもありたすでは、オブゞェクトのリストの最埌にコンマが衚瀺されるず、必然的に状況が発生したす。 知的蚀語では、プログラミング蚀語はこの状況を正垞ず芋なすべきですが、残念ながらほずんどの蚀語Cを含むはこれを゚ラヌず芋なしたす。 したがっお、束葉杖が発明されたした-特別な構文## __ VA_ARGS__。匕数のパッケヌゞが空の堎合にコンマを削陀したす。

プリプロセッサで文字列をラップするための軜量ルヌル


プリプロセッサ自䜓は非垞にく危険なものですさたざたな蚘事ぞのコメントで定期的に蚀及しおいたす。 しかし、それができたら、いく぀かの厳しい芁件を緩和するこずは非垞に論理的です。 特に、Cプリプロセッサは非垞に奇劙で愚かなバックスラッシュ構文を䜿甚しお耇数行マクロを実装したす。 この拡匵機胜を䜿甚するず、バックスラッシュの埌に空癜文字を含めるこずができたす文字は衚瀺されないため、コヌドの線集䞭に誀っお入力しおも気づかない堎合がありたす。

非巊蟺倀配列のむンデックス付け


今では明らかなように芋えたすが、C90では䜕らかの理由で非巊蟺倀配列にむンデックスを付けるこずができたせんでした。 幞いなこずに、これはC99ずC ++の䞡方で可胜です。

void *ポむンタヌず関数ポむンタヌを䜿甚した算術挔算


このようなポむンタヌでの算術挔算は蚱可されおいたす。 アドレス指定されたオブゞェクトのサむズは1バむトであるず想定されたすただし、これは奇劙な結果を意味したすsizeofvoidず機胜タむプのsizeofは1 ...これは良くありたせん。

修食子を持぀配列ぞのポむンタヌ


GCC Cの修食子constおよびその他を持぀配列ぞのポむンタヌを䜿甚した䜜業を実装するための暙準ずの埮劙な違い

非定数の初期化子


明らかなこずですが、暙準では、非定数オブゞェクトを初期化リスト䞭括匧で䜿甚するこずはできたせん。 この拡匵機胜はこの機䌚を開きたす

 foo (float f, float g) { float beat_freqs[2] = { fg, f+g }; /* ... */ } 

耇合リテラル


誰もがさたざたな角床からアプロヌチしたすが、完党に、取消䞍胜か぀正確にそれを実珟するこずはできたせんこれが最も重芁です。 配列、関数、および共甚䜓のオブゞェクトずしお䜿甚できる耇合リテラル-初期化だけでなく、単にコヌドでも-割り圓お、関数ぞの匕数ずしお枡すため。

 obj = ((struct foo) {x + y, 'a', 0}); char **tbl = (char *[]) { "x", "y", "z" }; 

このようなリテラルの堎合、察応するタむプの䞀時オブゞェクトが䜜成され、匏に参加したす。 したがっお、たずえば、これは可胜です定数は巊蟺倀ではないため、䞍可胜に思えたす。

 int i = ++(int) { 1 }; 

初期化リストの指定された芁玠


初期化リストのもう1぀の矎しい拡匵機胜-リスト内では、行内のすべおの芁玠だけでなく、蚘述子の構文を䜿甚しお特定の芁玠も指定できたす。 配列の堎合、これらは芁玠むンデックスが瀺されおいる単項角括匧です。 だから

 int a[6] = { [4] = 29, [2] = 15 }; 

ず同等

 int a[6] = { 0, 0, 15, 0, 29, 0 }; 

範囲を䜿甚できたす

 int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 }; 

構造の堎合、単項ドットを䜿甚した同様の構文が䜿甚されたす。

 struct point p = { .y = yvalue, .x = xvalue }; 

䞡方のタむプの指定子を混圚させるこずができ、䞡方の指定子ず同じ初期化リスト内の芁玠のみを䜿甚できたす。

 struct point ptarray[10] = { [2].y = yv2, {33,44}, [2].x = xv2, [0].x = xv0 }; 

ずころで、この拡匵機胜はC ++で実装されおおらず、暙準にドラッグされおいたせん。 残念なこずに、これは最も矎しい拡匵機胜の1぀であり、C ++ではなくCにあるものの1぀です。

ケヌスの範囲


caseステヌトメントずしおswitchステヌトメントで範囲省略蚘号付きを䜿甚する機胜

 switch(c) { case 'A' ... 'Z': /* ... */ break; } 

おもしろいですが、GCCの著者は、省略蚘号をスペヌスで囲むこずをお勧めしたす。そうしないず、敎数の解析に問題がある可胜性がありたすおそらく、数倀が実数ずしお認識されるこずを恐れおいたす。 適切な解析では、これはすべきではなく、同じ文字で始たる短い挔算子よりも長い挔算子が優先されるべきです。 たあ。

ナニオンのメンバヌであるオブゞェクトをナニオン型に倉換する


組合がある堎合

 union foo { int i; double d; }; 

intおよびdoubleオブゞェクトの型を明瀺的に型fooにキャストできたす。

  union foo u; int x; double y; u = (union foo) x; u = (union foo) y; 

同様に、匕数を関数に枡す堎合

 void hack (union foo); hack ((union foo) x); 

倉数宣蚀ずコヌドの混合


C90のC ++でよく知られおいるものも拡匵機胜ですC99では暙準に含たれおいたした。

関数、倉数、型、ラベル、列挙、制埡挔算子の属性


特別なキヌワヌド__attribute__ 。これにより、コンパむラヌ定矩の属性メタ情報をさたざたな蚀語構成芁玠に割り圓おるこずができたす。 キヌワヌドの埌に​​、属性名が括匧で瀺されおいたす。 属性は倧きく異なる堎合がありたす。 䞀郚の属性は䞀般的であり、他の属性は特定のアヌキテクチャに固有のものです。 属性には、属性名の埌にかっこで囲たれた匕数を含めるこずもできたす。 ここにいく぀かの属性がありたす実際、倚くの属性があり、おそらく、このトピックは別の蚘事に倀したす。

機胜属性
noreturn、-関数は制埡を返したせん。
pure-副䜜甚のない関数倀は匕数のみに䟝存したす、
format-圢匏文字列printfのスタむルの匕数がありたす。

ラベル属性
未䜿甚-ラベルはgotoでのナビゲヌトに䜿甚されたせん。
ホット-タグ付けの可胜性が高い
コヌルド-タグ付けの確率は䜎い

列挙芁玠の属性
非掚奚-芁玠の䜿甚は掚奚されおいたせん。コヌドで䜿甚された堎合、譊告が衚瀺されたす

挔算子の属性
fallthrough-switch / caseステヌトメントで䜿甚され、breakの代わりに蚭定しお、意図的にブレヌクがないこずをコンパむラに瀺したす。

可倉属性
敎列N-指定

叀いスタむルの関数定矩でプロトタむプを宣蚀する


叀いCずの互換性の束葉杖。これにより、新しいスタむルで関数のプロトタむプを宣蚀できたすが、関数の本䜓は叀いスタむルで定矩されたす型のない括匧内の匕数、型で匕数を分離し、䞭括匧で本䜓を分離。

C ++スタむルのコメント


あなたはそれを信じないでしょうが、䞀般的に蚀えば、それは拡匵機胜でもありたす-単䞀行コメントがただC暙準に含たれおいなかった叀代から残されたものです。 はい、そういう時がありたした。

識別子のドル蚘号


これが理にかなっおいるかどうかはわかりたせんが挔算子蚘号はほずんどありたせん、そのように-文字、数字、アンダヌスコアずずもに識別子にドル蚘号を䜿甚できたす。

゚スケヌプ蚘号


文字列たたは文字リテラルで「\ e」を䜿甚しお、文字を挿入したす。 文字はポヌタブル文字セットに含たれおいたせんが、POSIXにリストされおいない他の制埡文字よりも頻繁に必芁になるようです。

型たたは倉数フィヌルドのアラむメントのク゚リ


__alignof__キヌワヌドは、あるタむプのフィヌルドたたはあるタむプのフィヌルドに必芁なアラむメントを返したす。 アラむメント1-バむト境界に沿った可胜な限り最小、2-ワヌド境界に沿った、4-ダブルワヌド境界に沿った、など

むンラむン関数


これは、Cに移怍されたC ++のよく知られた機胜です。

volatileを䜿甚する


GCCでvolatileを䜿甚するいく぀かの機胜。 奜奇心から-コヌドにこれが含たれおいる堎合

 volatile int *ptr; /*...*/ *ptr; 

GCCは、これをptrが指すメモリからの読み取りずしお解釈し、適切なコヌドを生成したす

アセンブリ挿入物の䜿甚


GCCでのアセンブラヌむンサヌトの䜿甚を怜蚎。私が知っおいる限り、アセンブラヌ挿入のトピック自䜓は暙準の䞀郚ではなく、ここで説明するのに十分なほど広範です。アセンブラヌの挿入は、䞀般に別の蚀語の挿入の特殊なケヌスであるず蚀わなければなりたせん。2぀の構文の亀点であり、堎合によっおは互換性がないこずもありたす。どうやらこの理由で、GCCアセンブラヌの挿入は文字列のような匕甚笊で囲たれおいたす。

ヘッダヌファむルの代替キヌワヌド


別の芏栌ずの互換性のある束葉杖のようなもの。__const __、__ asm__などの単語

䞍完党な転送


芁玠なしでenumを宣蚀できたす。このタむプの倉数は宣蚀できたせんが、そのような列挙ぞのポむンタヌは宣蚀できたす。構造および関連付けずの類掚により、リストの名前の予備宣蚀の可胜性のために䜜成されたした。

文字列ずしおの関数名


これらはCでの反射の基瀎です。識別子__FUNCTION__たたは__func__および__PRETTY_FUNCTION__には、それらが䜿甚される関数の名前が含たれおいたす。__PRETTY_FUNCTION__には、拡匵名眲名が含たれたす。

呌び出し関数のアドレスずスタックフレヌムの取埗


関数呌び出しスタックぞのアクセスを実装したす。特別な組み蟌み関数組み蟌みを䜿甚しお、目的のレベル呌び出し偎関数、呌び出し偎を呌び出した関数などの戻りアドレス、および関数ずすべおの呌び出し偎関数のスタックフレヌムのアドレスを取埗したす。

ベクトル呜什の拡匵


倚くのプロセッサは、ベクタヌデヌタタむプず呜什をサポヌトしおいたすたずえば、SIMD-単䞀呜什、耇数デヌタ。

この拡匵機胜は、vector型の宣蚀vector_size属性を䜿甚ず、これらの型に察する通垞の操䜜の䜿甚をサポヌトしたす。型は基本的に配列ですが、その操䜜は通垞の倉数の操䜜に䌌おいたす。ただし、配列のようにむンデックスを䜜成できたす。

 typedef int v4si __attribute__ ((vector_size (16))); v4si a = {1,2,3,4}; v4si b = {3,2,1,4}; v4si c; a = b + 1; // a = b + {1,1,1,1}; a = 2 * b; // a = {2,2,2,2} * b; c = a > b; // c = {0, 0,-1, 0} c = a == b; // c = {0,-1, 0,-1} 

特別な組み蟌み関数__builtin_shuffleは、ベクトル内の芁玠を再配眮したり、むンデックスマスクに埓っお2぀から1぀のベクトルを圢成するためにも䜿甚できたす。

  v4si a = {1,2,3,4}; v4si b = {5,6,7,8}; v4si mask1 = {0,1,1,3}; v4si mask2 = {0,4,2,5}; v4si res; res = __builtin_shuffle (a, mask1); /* res is {1,2,2,4} */ res = __builtin_shuffle (a, b, mask2); /* res is {1,5,3,6} */ 

offsetofの特別な構文


構造䜓の先頭からのバむト単䜍のフィヌルドオフセットを返すoffsetof挔算子は、次の圢匏のマクロで実装できたす。

 offsetof(s, m) (size_t)&(((s *)0)-›m) 

ただし、これはC暙準では未定矩の動䜜でありれロ参照解陀のため、さたざたな䞍芁なコンパむラ譊告が発生したす。したがっお、組み蟌み関数__builtin_offsetofを䜿甚しおoffsetofを実装したす

さたざたな組み蟌み関数builtins


この抂念が独立した゚ンティティずしお目立぀こずはめったにありたせんが、無駄です。組み蟌み関数は、蚀語キヌワヌドず通垞の関数の䞭間であり、どこでも䜿甚されたす。ほずんどのプログラマヌは、その性質に぀いおも考えおいたせん。

たずえば、サむンサむン。芖芚的には、この関数は関数のように動䜜したすアドレスを取埗するこずもできたす。ただし、コンパむラレベルでは、このコンストラクトは関数呌び出しではなく1぀以䞊のアセンブラヌFPU呜什に倉換されたす浮動小数点をサポヌトしないアヌキテクチャのFPU゚ミュレヌションの堎合を陀く このような関数は組み蟌み関数ず呌ばれ、コンパむラヌによっお盎接生成されたす。これにより、ラむブラリヌ関数では利甚できない機胜を実装できたす。これらには、アトミックメモリアクセス、算術オヌバヌフロヌのチェック、Cilk Plus拡匵、数孊関数、特定のプラットフォヌムやプロセッサを操䜜するための倚くの関数などが含たれたす。

プラグマ


プラグマは、䞀般的な堎合に゜ヌスから盎接コンパむルプロセスを现かく制埡するためのディレクティブです。プリプロセッサず蚀語自䜓の䞡方に起因する可胜性がありたす実際、どこかに明確に垰属させるこずは難しく、プリプロセッサは長い間蚀語に統合されおいたす。GCCは、汎甚プラグマずプラットフォヌム固有プラグマの䞡方をサポヌトしおいたす。このトピックは倧きくお興味深いものであり、組み蟌みのものであるため、別のパヌトで説明するこずもできたす。

構造ず関連付けの名前のないフィヌルド


構造ず関連付けでは、ネストされた名前のない構造ず関連付けを宣蚀できたす。これらのネストされた構造ず関連付けのフィヌルドは、盎接利甚できたす。

 struct { int a; union { int b; float c; }; int d; } foo; foo.b = 10; 

これは、構造に名前がない堎合にのみ機胜するこずに泚意しおください。名前を付けお、そのようなアナりンスメントが包括的なネヌムスペヌス内のネストされた構造の宣蚀に倉わる堎合、぀たり、ネストロゞックはデヌタのネストからネヌムスペヌスのネストに倉わりたす。

たた、コンパむラオプションでPlan9拡匵モヌド "-fplan9-extensions"を有効にするず、Goでのみ䜿甚できる機胜を実行できたす。いく぀かの構造を他の構造に埋め蟌むこずができたす。構造䜓フィヌルドでは、別の構造䜓のフィヌルド党䜓を埋め蟌み、独自の構造䜓フィヌルドずしお参照できたす。C++継承ずは異なり、フィヌルドを埋め蟌む堎所を正確に指定できたす䜎レベルの目的にずっお重芁です。

 typedef struct { int a; } s1; //     typedef' typedef struct { int x; s1; int y; } s2; s2 obj; obj.a = 10; //     

スレッドロヌカル倉数


基本的に、スレッドロヌカルストレヌゞのスレッドメモリ領域に栌玍される静的スレッド倉数。ストリヌムやTLSなどが存圚する堎合は、そこに倉数を宣蚀するためのキヌワヌドが必芁です。

バむナリリテラル


70幎代にC蚀語ずずもに登堎するはずだった最も単玔で最も明癜なものの1぀。しかし、衚瀺されたせんでした。定数には、接頭蟞「0b」が䜿甚されたす。

公匏の方法がありたすが、8進定数の堎合、接頭蟞「0o」を入力する䟡倀があるこずに泚意しおください。先行れロの曞き蟌みメ゜ッドはひどいです。

GCC C ++拡匵機胜


volatileを䜿甚する


GCC C ++でvolatileを䜿甚するいく぀かの機胜、Cずの違い

制限付きポむンタヌC99から


restrictキヌワヌドを䜿甚するず、プログラマは、宣蚀されたポむンタヌが他のポむンタヌが指し瀺しおいないメモリヌのブロックを指しおいるこずをコンパむラヌに䌝えるこずができたす。耇数のポむンタヌが1぀のメモリブロックを指さないずいう保蚌は、プログラマヌによっお䞎えられたす。同時に、最適化コンパむラはより効率的なコヌドを生成できたす。

GCC拡匵機胜では、制限リンクを䜜成しおthisポむンタヌに適甚するこずもできたす。

あいたいなリンケヌゞ


C ++の䞀郚の構造では、オブゞェクトファむルにスペヌスが必芁であり、耇数の翻蚳単䜍で同時に衚瀺できたす。これらは、むンラむン関数、仮想関数テヌブルVTables、type_infoオブゞェクト、およびテンプレヌトのむンスタンス化結果です。GCCは、オブゞェクトファむルのCOMDATセクションでのそのようなオブゞェクトの配眮をサポヌトしたす。これにより、リンク段階での重耇オブゞェクトが排陀されたす。

むンタヌフェヌスおよび実装プラグマ


このようなプラグマを䜿甚するず、オブゞェクトがむンタヌフェむスであるか実装であるかをコンパむラに明瀺的に䌝えるこずができたす。「無限リンク」ぞの远加の束葉杖。

むンスタンスパタヌン


GCCでテンプレヌトをむンスタンス化する方法。特定のテンプレヌトパラメヌタに察しお、各テンプレヌトむンスタンスの1぀のコピヌのみが生成されるこずを保蚌するメ゜ッド。トピックは倧きいので、ここで蚀及したす。

クラスのメンバヌ関数ぞのポむンタヌから関数ポむンタヌを取埗する


操䜜 '-> *'および '。*'に関連付けられた機胜の明らかな拡匵。䜎レベルのクラスフィヌルドぞのポむンタヌがクラス内のこのフィヌルドのバむトオフセットである堎合、メ゜ッドポむンタヌは本栌的な関数ポむンタヌであり、GCCはメ゜ッドポむンタヌの型を通垞の関数ポむンタヌにキャストする機胜を远加したす。

C ++属性


䞀郚の属性__attribute__キヌワヌドで指定は、C ++にのみ適甚できたす。いく぀かの䟋abi_tag-倉数名ず関数名のマングリングを指定する方法。init_priority-グロヌバルオブゞェクトの初期化優先順䜍。

耇数の機胜バヌゞョンの宣蚀


奜奇心opportunity盛な機䌚。タヌゲット属性を䜿甚するず、プロセッサの特性たずえば、1぀たたは別のコマンドセット、1぀たたは別のプロセッサモデルなどのサポヌトの可甚性に応じお、同じ関数の耇数のバヌゞョンを宣蚀できたす。条件付きコンパむルに倚少䌌おいたすが、すべおの関数がコンパむルされ、実行時に必芁な関数が遞択されたす。

関連付けられた名前空間


この機胜は、むンラむン名前空間ず同等ですしたがっお、非暙準の実装はGCCの将来のバヌゞョンで削陀されたす。

タむプ特性


コンパむル時にさたざたなタむプの情報をコンパむルできる特別な構造のコンパむラレベルのサポヌト。それらの倚くがあり、おそらくこのトピックを個別に怜蚎するのが理にかなっおいたす特に、テンプレヌトに実装された類䌌の構造やD蚀語の類䌌の構造ず比范しお。これが䜕であるかを明確にするために、ここにいく぀かの芁玠がありたす。

 __is_abstract (type) __is_base_of (base_type, derived_type) __is_class (type) __is_empty (type) __is_enum (type) __is_literal_type (type) 

C ++の抂念


最も匷力な機胜。残念ながら、最新のC ++ 17暙準に該圓したせんでした。テンプレヌト匕数に明瀺的に制限を蚭定する方法぀たり、テンプレヌトの䞀意の入力を導入するにより、メタプログラミングをより簡単に、より理解しやすくしたす。

掚奚されないか、既に削陀された機胜


おもしろい。 これらの機胜は削陀されるか、䜿甚が掚奚されおいないず宣蚀されおおり、たもなく削陀されたす。


䞋䜍互換性


以前のバヌゞョンのC ++およびCずの䞋䜍互換性のいく぀かの機胜。これらの機胜は、特別なコンパむラオプションに含たれおいたす。


今のずころすべおです。


ご芧のずおり、䞀郚の拡匵機胜は拡匵機胜ず呌ばれるこずさえほずんどありたせんこれらはよく知られおいる機胜であるか、さらに悪いこずに、䞀郚の叀代および継承された暙準ずの互換性を確保し、蚀語蚭蚈の倱敗した決定を回避するように蚭蚈された束葉杖などです

同時に、他のものは蚀語機胜の真の真珠であり、それらが暙準に含たれおいないのは残念です。

Source: https://habr.com/ru/post/J315676/


All Articles