C言語のスクラップ4:_Pragmaを使用してAPIを穏やかに破棄します

I.はじめに

この作業シナリオを想像してみてください。プロジェクトの関数ライブラリを作成していて、他の人がライブラリで提供されている関数を呼び出すと、ライブラリ内の関数Aが
冗長
であることがわかります

完璧なプロットでは、この関数Aを破棄したいだけです。現時点では、この関数を呼び出した他の人の数がわからないため、直接削除することはできません

この状況にうまく対処するにはどうすればよいですか?

この短い記事でこの問題について話しましょう。

第二に、操作プロセス

1.ライブラリの最初のバージョン

テストファイルは、api.h、api.c、main.cの3つだけです

  1. api.hおよびapi.c:ライブラリファイル、コンパイル済みlibapi.so;
  2. main.c:上記で生成されたライブラリlibapi.soを使用して、実行可能プログラムを生成します。

ドキュメントのapi.hコンテンツ:2つの関数のステートメント

api.cファイルの内容:2つの関数の定義

ライブラリファイルlibapi.soをコンパイルしますコンパイル手順:

gcc -fPIC -shared api.c -o libapi.so

Main.cファイルの内容:

実行可能ファイルをコンパイルします。

gcc main.c -o main -L./ -Wl,-rpath=./ -lapi

上記のコードの単純さは、helloworldと同等です。

2.ライブラリの2番目のバージョン

これで、init関数は冗長だと思います。削除したい場合、次のように変更できます。

api.cファイルで、init()関数を削除します。

api.hファイル内容が次のように変更されます。

キーコードは次の行です。

#define init()               (1) API_DEPRECATED

api.cファイルによってこの関数が削除されましたが、この関数はmain.cファイルで呼び出されるためinitシンボルマクロ定義の形式で提供されます

言い換えると:

最初のバージョンでは、main.cファイルのinitコンパイラによって処理される関数であり、この関数のアドレスはリンクフェーズ中にlibapi.soライブラリから検出されます。

2番目のバージョンでは、initはマクロとして定義され前処理段階で後者置き換えられ(1) API_DEPRECATEDます。

(1)はマクロ置換の式です。この関数はif条件の判断に使用できるため、値を返す必要があります。
API_DEPRECATEDは別のマクロ定義であり、実行可能プログラムのコンパイル時にコンパイラーがメッセージを出力できるように拡張されています。

実行可能ファイルをコンパイルすると、コンパイラは次の段落を出力します。

gcc main.c -o main -L./ -Wl,-rpath=./ -lapi

これは本来の目的を達成しました!これは、ユーザーに注意を促すためです。この関数は非推奨になりました。使用しないことをお勧めします。

3つの_Pramaその他の使用法

_Pragmaは、標準の一部であることを除いて、Microsoft固有の__pragmaキーワードに似ています。C99でC導入されました。c ++の場合、c ++ 11で導入されました。
これにより、命令をマクロ定義に配置できます。

1.ヘッダーファイルの繰り返しインクルードへの対処

ヘッダーファイルでは、繰り返しインクルードするのを防ぐために、一般的に3つの方法で処理します。

(1)最初のアプローチ:

#ifdef   MY_API
#define  MY_API

// 头文件内容

#endif

(2)2番目の処理方法

#pragma once

// 头文件内容

上記の2つの方法はどちらも、同じヘッダーファイルが繰り返しインクルードされるのを防ぐことができますが、それでもいくつかの違いがあります

最初の方法:プリプロセッサは引き続きファイル検索してファイルを開き、ファイルの内容を読み取った後、MY_APIが定義されているかどうかを確認する必要があります。

2番目の方法:これはハイエンドのメカニズムであるため、コンパイル速度を上げることができます。コンパイラは、ヘッダーファイルの#ifndefと#endifを判断する必要なしに、ファイル名を自動的に比較するため中間検索が行われます。され、省略、オープンと操作をお読みください。

(3)3番目のアプローチ

_Pragma("once")

この方法と2番目の方法の違いは次のとおりです。

#pragma:は前処理命令であり、言語標準外の情報をコンパイラに伝達するために使用され、マクロでは使用できません
。_Pragma:は言語標準に属する演算子であるため、マクロにネストできます。上記の例では、

#pragmaはコンパイラの拡張ですつまり、コンパイラによって決定されます。コンパイラAはサポートしているかもしれませんが、コンパイラBはサポートしていない可能性がありますが、この可能性は比較的小さいです。

_Pragma演算子は、言語レベルの標準です。これは標準であるため、コンパイラは標準に従う必要があります。したがって、この方法もお勧めします。

HouJieの先生がC ++ビデオレッスンで言ったことを思い出してください。私たちはコードを書くだけでなく、機能を適切に保証するだけでなく、コードを素晴らしい雰囲気の中に置きます_Pragmaを使用すると、#ifndefよりも雰囲気が増すと思います。

2.コンパイル情報を出力します

#pragma message("the #pragma way")
_Pragma ("message( \"the _Pragma way\")") 

上記の2行の内容と出力情報は同じですが、ネストされた二重引用符は円記号でエスケープする必要があることに注意してください。

以上です。素晴らしい週末をお過ごしください。


良い記事 を転送 する 必要があります;共有すればするほど、あなたは幸運になります!


推奨読書

[C言語]
1。C言語ポインター-基本的な原則から高度なスキルまで、完全に説明するのに役立つ画像とコード付き
2.元のgdbの基本的なデバッグ原則はとてもシンプルです
3.ステップバイステップの分析-Cを使用してオブジェクト指向プログラミングを実現する
4.コード強制を改善するための武器:マクロ定義-エントリから放棄まで
5. C言語でsetjmpとlongjmpを使用して、例外のキャプチャとルーチンを実装する

【アプリケーション設計】
1.ソフトウェアアーキテクチャを階層化してモジュールに分割する必要があるとの意見とその方法(1)
2。ソフトウェアアーキテクチャを階層化してモジュールに分割する必要があるとの意見とその方法(2)
3。IoT
ゲートウェイ開発:MQTTメッセージバスベースの設計プロセス(パート1)4。IoTゲートウェイ開発:MQTTメッセージバスベースの設計プロセス(パート2)
5。プロセス間の私のお気に入りの通信方法-メッセージバス

【オペレーティングシステム】
1.なぜ宇宙船やミサイルは、組み込みシステムではなくマイクロコントローラーを好むのですか?

[
モノのインターネット] 1。暗号化と証明書に関するもの
2.LUAスクリプト言語を深め、デバッグの原理を完全に理解できるようにする

[ナンセンス] 1。私の失敗したキャリア経験に基づく
:職場に不慣れな技術者のためのいくつかのヒント

おすすめ

転載: blog.csdn.net/u012296253/article/details/115366935