C/C++プログラミング習慣

12424 ワード

コードは常にバグがありますが、この点ではないほうがいいです.効率はプログラマーがしなければならないことであり、間違いなくプログラマーの一生の追求である.多重化、分而治之、折衷はコード哲学の基本思想である.モジュール化とオブジェクト向けは,効率的な誤りのないコードを実現する方法である.効率的な誤りのないコードは思想と実践の絶えず繰り返しを必要とする.
1.2.1命名規則
命令規範は基本的にマイクロソフトが推薦したハンガリー命名法を採用し、やや簡略化されている.
1.定数
定数は大文字と数字で構成され、CPUのように下線で区切ることができます.8051.
2.変数
変数は小文字(変数タイプ)のアルファベットで始まり、中央は大文字で区切られ、変数ドメイン接頭辞(変数アクティブドメイン接頭辞の下に線で区切られた)を追加できます.例:v_nAcVolMin(交流電圧最小値).変数ドメイン接頭辞は、次の表のローカル変数を参照してください.変数名の意味が明らかであれば、接頭辞を付けず、煩雑さを回避します.例えば、ループに用いるint型変数i,j,k;float型の3次元座標(x,y,z)など.
3.関数名は一般的に大文字で始まり、中央はSetSystemParaのように大文字で区切られます.
関数の名前は動賓形式を採用している.関数が最下位の場合は、すべての小文字で、単語間に下線の形をとることが考えられます.下位グラフィック関数:pixel、lineto、およびキーボード読み取り関数get_keyなど.
4.符号名は共通または具体的な意味を持つべきで、可読性が強い.特にグローバル変数では、静的変数の意味が明確でなければなりません.
C++のキーワードの一部は、class、new、friendなどのシンボル名として使用できません.符号名の長さは31個未満で、ANSI Cと一致している.ネーミングには26文字、10文字、下線''しか使用できません‘$’‘@’などの記号は使用しないでください.下線''使用は目立つべきで、記号の頭の尾に現れず、記号の真ん中にしか現れず、2つ連続して現れない.
5.プログラムに意味のない数字は少なく、定数はできるだけマクロで置き換えます.
1.2.2アサーションの使用
プログラムは一般的にDebugバージョンとReleaseバージョンに分けられ、Debugバージョンは内部デバッグに使用され、Releaseバージョンはユーザーに発行されます.アサートは、Debugバージョンでのみ機能するマクロであり、「あり得ない」ことを確認するために使用されます.以下はメモリレプリケーションプログラムです.実行中にassertのパラメータが偽の場合、プログラムは中止されます(一般的には、assertがどこで発生したかを示すプロンプトダイアログも表示されます).
//         



void memcpy(void *pvTo, void *pvFrom, size_t size)



{



void *pbTo = (byte *) pvTo;



void *pbFrom = (byte *) pvFrom;



assert( pvTo != NULL && pvFrom != NULL );



while(size - - > 0 )



*pbTo + + = *pbFrom + + ;



return (pvTo);



}

 
assertは急いで組み合わせたマクロではなく、プログラムのDebugバージョンとReleaseバージョンで差をつけないために、assertは副作用を生むべきではありません.だからassertは関数ではなくマクロです.プログラマーはassertを任意のシステム状態で安全に使用できる無害なテスト手段と見なすことができる.
以下に、断言を使用するいくつかの原則を示します.
1)断言を用いて発生すべきでない不正を捕捉する.不法な状況と誤った状況の違いを混同しないでください.後者は必然的に存在し、必ず処理しなければなりません.
2)断言を用いて関数のパラメータを確認する.
3)関数を記述する際には,繰り返し考査を行い,「どのような仮定をするつもりですか」と自問する.いったん確定した仮定は,断言を用いて仮定を検査する.
4)一般教科書ではプログラマーたちに誤り防止のプログラム設計を奨励しているが,このようなプログラミングスタイルは誤りを隠すことを覚えておく必要がある.誤り防止プログラミングを行う場合、「起こり得ない」ことが確実に発生した場合は、断言を用いてアラームを鳴らす.
1.2.3最適化/効率規則
ルール1:volatile定義は、割り込み関数/スレッドおよび外部関数で使用されるグローバル変数に適用されます.
例:
volatile int ticks;



void timer(void) interrupt 1 //      



{



ticks++



}



void wait(int interval)



{



tick=0;



while(tick<interval);



}

 
volatileを使用しない場合、whileループは空のループであるため、コンパイラが最適化されると(コンパイラはこの変数が割り込みで使用されていることを知らない)、ループは空の操作に最適化されます!これは明らかに間違っている.
ルール2:あまり複雑な文を書かないでください.コンパクトなC++/Cコードは効率的なマシンコードを得ることができませんが、プログラムの理解性を低下させ、プログラムが間違っている確率も向上します.
ルール3:変数タイププログラミングにおける応用原則:
シンボル演算に時間がかかるため、できるだけ小さいタイプ(Floatを使わないでできるだけ使わないでください)とシンボルレスUnsignedタイプを採用します.
同時に、関数の戻り値もできるだけUnsignedタイプを採用することで、異なるタイプのデータ比較演算による暗黙的なエラーを回避するというもう一つのメリットがあります.
1.2.4その他の規則
ルール1:複数の機能を一体化した関数を記述しないで、関数の戻り値の中で、正常値とエラーフラグを混同しないでください.
ルール2:BOOL値TRUEとFALSEを1と0に対応させてプログラミングしない.
ほとんどのプログラミング言語ではFALSEは0と定義され、0以外の値はTRUEです.Visual C++はTRUEを1と定義し、Visual BasicはTRUEを-1と定義する.
例:
BOOL flag;



…



if(flag) { // do something } //      



if(flag==TRUE) { // do something } //      



if(flag==1) { // do something } //      



if(!flag) { // do something } //      



if(flag==FALSE) { // do something } //       



if(flag==0) { // do something } //       

 
ルール3:「==」を「=」と書かないように注意し、コンパイラは自動的にこのエラーを発見しません.
ルール4:統一関数の戻り値は符号なし整形を推奨し、0はエラーなし、その他はエラータイプを表す.
1.3モジュール化Cプログラミング
C言語はC++のオブジェクト指向の成分を備えていないが,オブジェクト指向の思想を吸収し,モジュール化プログラミングの構想を採用すべきである.
オブジェクト向けの思想とオブジェクト向けの言語は2つの概念である.オブジェクト向けでない言語でもオブジェクト向けのプログラミングができるので、C++の誕生を考えてみましょう.C++がCに対して傲慢と偏見を持つ理由はなく、いかなる場合でもC++方法が問題を解決する良薬ではなく、例えば埋め込みシステムの効率と空間の二重需要に直面している.コンパイラではなく、方法について話しています.
Cのソフトウェア開発において最も重要な問題は、データアクセスの制御(パッケージ)の欠如であり、Cプログラマは、extern形式のグローバル変数を大量に使用して各モジュール間でデータを交換している.このように複数の変数が複数のモジュールに現れ、剪断が絶えず乱れていて、ある日やっと「人」を探すのが難しいことに気づいた.一つのものはおいしくて、知者は浅く改善して、愚か者は死ぬまでしかありません.Cの上で多く工夫するべきで、やはりC言語がどのようにモジュール化のプログラミング方法を実現するかを見て、部分的にOO特性のパッケージと多態を備えています.
具体的に述べる前に,生存期間と可視性の概念を明確にする必要がある.生存期間とは、メモリ内の変数の生存期間を指し、可視性とは、変数が現在の位置で使用可能かどうかを指します.両者は緊密に結びついているが,混同してはいけない.一人が存在するが見えないのは神や魂としか解釈できない.一つの変数が存在するが見えないのは不思議ではない.モジュール化方法は静的関数、静的変数などの「精霊」たちの特殊な生存期間と可視性を利用している.
最後に明確な点は、ここのモジュールが1つであることである.Cファイル単位.
ルール1:関数を使用してルールと静的関数を命名する
モジュール内で他のモジュールに呼び出されない内部関数には、すべての小文字、単語間の下線付きの命名規則が使用されます.下位グラフィック関数:pixel、lineto、およびキーボード読み取り関数get_keyなど.これらの関数はstatic静的関数として定義され、他のモジュールがこれらの関数を誤って呼び出すと、コンパイラはBCコンパイラなどのエラーを与えることができます.(注:一部のコンパイラではエラーを報告できませんが、コードスタイルが一致し、関数階層が明確であるため、このようにすることをお勧めします).
ルール2:静的変数の利用
モジュール内で他のモジュールに読み書きできないグローバル変数はstatic宣言を採用しなければならない.これにより、他のモジュールがこれらの変数を誤って読み書きした場合、コンパイラは警告(C 51コンパイラ)またはエラー(BCコンパイラ)を与えることができる.
ルール3:OOインタフェースの概念とポインタパラメータモジュール間のデータインタフェース(すなわち関数)を導入するには、どのインタフェースが必要なのか、インタフェースを通じてどのデータを操作する必要があるのか、できるだけインタフェースの不変性を行う必要があるのかを事前に十分に考慮しなければならない.
モジュール間のデータ交換はできるだけインタフェースを通じて完成し、方法は関数を通じてパラメータを伝達し、プログラムの効率を保証し、スタック空間を減らすために、大量のパラメータ(例えば構造)を伝達するにはアドレス方式を採用し、ポインタを通じて関数パラメータまたは関数としてポインタを返し、できるだけextern形式のグローバル変数を根絶し、extern形式のグローバル変数であることに注意してください.モジュール内のグローバル変数は許可され、必要です.
ポインタパラメータの増加のオーバーヘッドは主にパラメータとしてのポインタと局所ポインタのデータ空間(C 51などの組み込みシステム)がスタック空間が限られているため、関数パラメータが外部RAMのスタックに置かれることが多い)であり、増加したコードオーバーヘッドは関数の呼び出しだけであり、良好なモジュール化構造をもたらす.また、インタフェース関数を使用すると、コード内の複数の場所でグローバル変数を直接使用するよりも、コード空間を大幅に節約できます.頻繁にアクセスする必要がある変数に対してインタフェース伝達を使用する場合、関数呼び出しのオーバーヘッドは大きく、externグローバル変数を使用することを考慮する必要があります.
次の2つのCモジュールのデータ交換を示します.
//Module1.C



OneStruct* void GetOneStruct(void); //    1    



void SetOneStruct(OneStruct* pOneStruct); //   1    



struct OneStruct



{



int m¬_imember;



//……



}t1;



//  1   //t1     …..



OneStruct* void GetOneStruct(void)



{



OneStruct* pt1; //          



t1.imember=15;



pt1=&t1;



return pt1;



}



void SetOneStruct(OneStruct* pOneStruct)



{



t1.imember=pOneStruct->imember;



//…….



}



//Module2.C



void OperateOneStruct(void); //  2    1         1   



OneStruct* void GetOneStruct(void);



void SetOneStruct(OneStruct* pOneStruct);



void OperateOneStruct(void)



{



OneStruct* pt2; //          



pt2=GetOneStruct(); //    



SetOneStruct(pt2); //    



}

 
インタフェースを使用してデータにアクセスすると、関数の戻り値が右にしかならないため、グローバル変数はそうではありません.
例えばcOneChar==4;cOneChar=4と間違えられる可能性があります.
ルール4:限られたパッケージとマルチステート
C++のclassはCのstructに由来することを忘れないでください.C++の虚関数メカニズムは実質的に関数ポインタです.データ・メソッドをカプセル化し、ハードウェアに関連するデータ構造など、コードの再利用度を向上させるためには、データ構造にアクセスする関数を構造内部の関数ポインタとして定義することを推奨します.このようにハードウェアが変化すると、そのハードウェアにアクセスする関数を書き換える必要があり、書き換えた関数アドレスをその関数ポインタに割り当てる限り、上位コードは関数ポインタを使用するため、全く動かず、コード再利用を実現する.また,この関数ポインタはパラメータやグローバル変数を伝達することで上位コードに伝達できるので便利である.
例:
struct OneStruct



{



int m¬_imember;



int (*func)(int,int);



//……



}t2;



 


原文リンク:http://blog.chinaunix.net/uid-25445243-id-3366202.html