記事のディレクトリ
I.はじめに
この作業シナリオを想像してみてください。プロジェクトの関数ライブラリを作成していて、他の人がライブラリで提供されている関数を呼び出すと、ライブラリ内の関数Aが
冗長であることがわかります。
完璧なプロットでは、この関数Aを破棄したいだけです。現時点では、この関数を呼び出した他の人の数がわからないため、直接削除することはできません。
この状況にうまく対処するにはどうすればよいですか?
この短い記事でこの問題について話しましょう。
第二に、操作プロセス
1.ライブラリの最初のバージョン
テストファイルは、api.h、api.c、main.cの3つだけです。
- api.hおよびapi.c:ライブラリファイル、コンパイル済みlibapi.so;
- 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。私の失敗したキャリア経験に基づく
:職場に不慣れな技術者のためのいくつかのヒント