• ベストアンサー

[雑談]コーディング規約への思い

今までに皆さんが体験されたことのある記憶に残るコーディング規約を教えていただきたいです。 これはお勧めとか、こんな酷い規約があった、自分専用ルール等、否定は無しで軽い気持ちで教えていただきたいです。 私の記憶に残る規約は下記があります。 [意外と良いかもと思ったもの] ・一文字のループカウンタの使用の禁止 少しでも検索を楽にしましょうと理由でした。 ×:for(i=0; i<10; i++){ ○:for(ii=0; ii<10; ii++){ [勘弁して欲しかったもの] ・if(2==ii)のように条件文を通常とは逆に書く。 ==の比較をタイプミスで=とした時にコンパイルが通らなくするためにらしいです。慣れるまで相当時間がかかりました。 ・3項演算子の使用禁止 読めなくて、理解もしなくてその前後のコードを修正する人が居て、使用禁止になったようです。。。 [自分専用規約] ・自分にごめんなさいと言うまで動的なメモリ確保はしない。 リーク対策です。動的にメモリを確保しないと実装できない場合や無駄にメモリを使用しすぎる場合にだけ、自分にごめんなさいをしました。 泣く泣く動的にとる場合はmallocではなくcallocを必ず使うようにしてました。 ・極力関数化 if文やswitch文が長くなる場合は、それを条件判断関数としてわざわざ関数を作る努力をします。 普通の処理も一連の流れなら必ず関数化します。 コードの可視性が上がりましたし、デバッグが楽になりました。 (ある関数をデバッグする場合、大半が関数化しているので戻り値だけチェックすればいいので) でも、関数1から関数2に飛んで、さらにその関数2から関数3に飛ぶ等全ての関数を追えば関数1に戻ってきた時に関数1の内容を忘れるような深すぎるのは禁止にしてました。 また関数名も相当こだわってました。 実はコメントを和英併記してくれと言われた時にコメント量を少なくする為にやってたのが癖になったのは内緒です。 ・無駄コメントの削除とconstの推奨 × int result = 0; result=NanikanoKansuu(); //NankanoKansuuが正常に処理したら if(result==0){ ○ int result = 0; const int normalProcess = 0; result=NanikanoKansuu(); if(result==normalProcess ){ ×のコメントを書くのはどうも抵抗がありました。戻り値なんてメンテなどでソースを追う際に読めばわかるやん!って思ってしまって。。。 それにアプリケーションの歴史が長く、メンテに次ぐメンテでコメントが良く間違ってるソースに当たり、コメントをあまり信用しなくなりました。 [微妙だと思った規約] ・プリフィックスの使用 仕様変更に伴いデータ型を変更する際に絶対に変数名の置換を忘れる!と確信できるメンバーがいる時に思いました。 考えればどんどん出てきそうですが、これくらいにしておきます。 見直すとレベルの低い発想が多いですね。ちょっと恥ずかしいです。

noname#96502
noname#96502

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

[意外と良いかもと思ったもの] (1)bool型同士の比較について falseは大概のコンパイラ・処理系において0だが、trueは0x01や0xffの可能性があるため、各コンパイラで作成したライブラリを結合した場合でも問題なく条件を判断出来るようにするため、必ずfalseと比較するようにする。 (「trueと等しいか」ではなく、「falseと違うか」) (「trueと違うか」ではなく、「falseと同じか」) (2)変数名の記述(ハンガリアン文字)について 変数名の頭に型を識別できる識別しをつける「ハンガリアン文字」について、非賛成の記述をされているホームーページがありました。 私もそれを見たときに同感しました。 理由としては、その型で格納できる値の範囲を超えてしまったときに、イチイチ置換する必要があるためです。

noname#96502
質問者

お礼

教えていだたきありがとうございます。 >(1)bool型同士の比較について 知りませんでした。 非常に勉強になりました。ありがとうございます。 >(2)変数名の記述(ハンガリアン文字)について 非常に恥ずかしいです。 質問の最後のプリフィックス→ハンガリアンに訂正させていただきます。 オーバフローしてたみたいです。。。 もちろん激しく同意です。 気になってたのですが、この質問はアンケートにも該当しそうで、規約違反になりそうなので1回〆ます。

その他の回答 (1)

noname#101303
noname#101303
回答No.1

以前、こういう書き方をどこかで「習ってきた」方がいました。 if(a==b){ }else{  式; } 「true」側は何も記載されていません。 最後まで納得できませんでした…。 (なぜ、(a!=b)に出来ないのだろう?)

noname#96502
質問者

お礼

情報ありがとうございます! きっとそのコードを書かれた方はコンパイラが嫌いなんですよ! 一人きりの時にif(a!=b){式;}って書いた時との実行ファイルのデータを比較してるはずです! 嘘です。。。私もそのコードは納得できません。 人のコードは納得できない私は、過去に似たようなコードを書いた事があります。。。 ret=pollingFunk();//ポーリング系の関数 if(ret){ //上手く行ってるので何もしないよ~ } else{ //リトライ処理 式; } if文の中で何も処理してない点は一緒ですね。 でもコメンだけちゃんと書いてるんです! 正常系を拡張したかったらここに処理を入れてねというメッセージです。いや愛です! すいません。言い訳しました。。。

関連するQ&A

  • あなたのC言語コーディング規約

    勤務先・学校・趣味でC言語を使用してプログラムをしている方の多くは組織内で決めているコーディング規約に沿ってプログラムをしていると思います。 しかし、全てに関して規約化されていることは少なく、ある程度プログラマの裁量に任せていることがあると思います。 そこで、質問です。 「あなたの中で決めているコーディング規約は何ですか?」 「また、その理由は何ですか?」 私が決めているコーディング規約を一例挙げると以下の通りです。 (基本は他人が見ても直ぐに理解できるように心がけてます。) ------ □変数名の前には必ず型を現す文字を書く 理由:観ただけで型が分かるから。 例 :int型は、iData    char配列は、stData    ポインタは、pData □関数の復帰値は、一旦必ず変数に代入する。 理由:代入しないとデバックがしにくい。 例 :iRetCode=func();    switch(iRetCode){      case文    }    の、ように色んな値を試すときに不便。 □if文には、極力「!」(NOT)は使用しない。 理由:複数の論理和・積などが入った場合ややこしいので    elseで代用する。(真の時の処理はわざと書かない) □if文の判定には必ず定数値を左辺に持ってくる。 理由:if(iData=0)とかの"=="を"="にしてしまうミスを防ぐため。    (コンパイラによっては、警告が出るものもありますが…) 例 :if(0=iData)など □while(1)は、基本的に使用しない。 理由:無限ループに陥らないようにするため。 ------

  • const int&の戻り値について

    const int&の戻り値について c++で「const int&(const int a)const{...」についてのメンバ関数がありますが、そのconst int&はどういう意図に使われるのでしょうか。 &があるので、アドレスを返すと思いますので、ポインタ変数に入れるだけでしょうか。それでもポインタ変数とメンバ関数の戻り値のアドレスは違うのはどういうことでしょうか。 主な使い用途がありましたら、教えてください。

  • 今風(?)のコーディング規約が知りたい

    C++ は初心者です。他の言語は結構長くやっております。C は多少経験があります。(が、知識が 10 年くらい前のものです) 趣味で C++ を始めたのですが、仕事や大きなコミュニティ内で使ったことがないために、今現在主流のコーディング規約というかお行儀の良いスタイルの判別が難しいです。ヘッダファイルや Google Codesearch 等で片っ端から色々なソースを見ているのですが結構バラバラなんですよね・・・ 他の言語の経験があるので、switch の最後には何もなくとも default を明確につけとけ みたいなことの有用性はわかるのですが ではなくて、細かいですけど if (hoge) { } なのか if (hoge) { } なのか、とか (自分は下の方が好き) int ←ここで改行する?(自分は改行する) hogeHoge() { ・・・ とか。 多分僕の個人的な好みは大昔にやった C (K&R スタイル?) や長く仕事で使っている Perl の影響が強い気がするので、C++ 的にはどうなのかなと。 変数名や関数名は GNU スタイルなのか キャメルスタイルなのか、キャメルスタイルだったら大文字から始めるのか、関数名だけ大文字から始める人もいれば、関数名も小文字からの人もいるし、enum の定数は全部大文字が普通?とか(きりないですorz)・・・ ハンガリアンはもう推奨されてないというのは理解してます。その理由もなんとなく。でもハンドルは hHoge にするのが普通みたいですし、bool型なら is~ とか can~ とか。人によってはグローバル変数にもプレフィックスつけるようですね。他にもそういうこれはプレフィックスつけるのが普通!ってのがあったら知りたいです。僕自身はめっちゃ長くなっても意味が正確にわかる変数名をつけとけ派なので、プレフィックスにはあまり必要性を感じないです。(英文みたいな変数名とか良くやる) でも、 C++ 長くやると多分考え方が変わるかなあと思うので。 とりあえず以下を読んでますが、それほど間違った選択はしていないでしょうか? http://sec.ipa.go.jp/download/dl.php?filename=report/200606/CMGuide_V1-0.pdf http://www.possibility.com/Cpp/CppCodingStandard.html それはもう古い、今はこういう感じが普通、というのがあったら教えていただけると幸いです。(英語でも構いません) 個人で趣味レベルでやるなら、その程度は好きにしてかまわんでしょう、という意見でも OK です。好きにするんでも一貫したいので、どうせなら良いものを参考にしておきたいとは思ってます。(目的のモノを動かすのに数時間もかからなかったのに、そのコードをお行儀よく書き直そうとして数日も定まらずに何度も書き直したり・・・な状態なので。)

  • strtol関数をmalloc()関数を使用して次のソースプログラムを

    strtol関数をmalloc()関数を使用して次のソースプログラムを修正しなさいを言われました。 どなたか詳しい方よろしくお願いします。 #include <limits.h> #include <ctype.h> #include <errno.h> #include <stdio.h> int _space_sign(const char *s, const char **endptr); int _space_sign(const char *s, const char **endptr) { int sign ; while (isspace((unsigned char)*s)) ++s; sign = 0; switch (*s) { case '-': sign = -1; // fall through case '+': ++s; break; } *endptr = s; return sign; } long int strtolong(const char * s, char ** endptr, int base) { int c; int sign = _space_sign(s, (const char**)&s); long result; if (s[0] == '0') { ++s; if ((s[1] | 0x20) == 'x') { if (base == 0 || base == 16) { ++s; base = 16; } } else if (base == 0) base = 8; } else if (base == 0) base = 10; result = 0; for (; c = tolower((unsigned char)*s), isdigit(c) || ('a' <= c && c <= 'v'); s++) { int d ; if( isdigit(c) ) d= c - '0' ; else d = c - 'a' + 10; if (d >= base) break; if (result > (LONG_MAX - d - sign) / base) { errno = ERANGE; result = sign ? LONG_MIN : LONG_MAX; } else { result = result * base + d; } } if (endptr != NULL) *endptr = (char*)s; if (sign != 0) result = -result; return result; } int main(void) { char s[128], *e; long n; int base; printf("何進数で変換しますか。"); scanf("%d", &base); printf("変換する数値を入力してください。"); scanf("%s", s); n = strtolong(s, &e, base); if (errno != ERANGE) { printf("変換数値=%ld\n", n); if (*e != '\0') { printf("変換不可能部分=%s\n", e); printf("%d文字目の\'%c\'が変換不可\n", e-s+1, *e); } } else if (n == LONG_MAX) printf("long値で表現できる値を上回りました。\n"); else if (n == LONG_MIN) printf("long値で表現できる値を下回りました。\n"); return 0; }

  • bsearch関数の呼び出しで

    C言語の深いところまで理解しようとしてます。今まで使わないだろうと思っていた関数へのポインタ なのですが、 2分探索のところで bsearch関数というのが出てきました。 この関数は第5引数に比較関数を引数にするのですが p = bsearch(&ky, x, nx, sizeof(int), (int (*)(const void *,const void *))int_cmp ); という形でサンプルソースには載っています。 この (int (*)(const void *,const void *))int_cmp の部分なのですが、まず戻り値をキャストするなら int (*)ではなく(int *)ではないでしょうか。 それとint_cmpは比較関数なのですが、引数が左側に来る、というところが納得できません。 ちなみにソースファイルをcppのままだとコンパイルできませんでした.cに拡張子を直したらコンパイルできました。 説明が足りないところがあったら指摘してください。お願いします。

  • マクロ内での変数定義

    C言語においてのマクロの仕様を教えてください。 (1)マクロ内でコメントは不可なのでしょうか? (2)マクロ内で変数定義は不可なのでしょうか?  マクロは実行された場所に展開されるだけの認識ですので、  マクロ内で変数宣言されている場合、関数の先頭でしかマクロが使えない? よろしくお願い致します。 ----以下作成コード---- #define TESTMACRO(result,a,b) \ do{ \ int tmpData = 5; \ if( a=0){ \ result = -1; \ continue; \ } \ if( b=0){ \ result = -1; \ continue; \ } \ result = a*b*100; \ }while(0) int main(){ int result = 0; /* 他の処理 */ TESTMACRO(result,a,b);  /* 結果resultのログ表示 */ }

  • 戻り値を返す関数の前に(void)を付ける

    今日会社で 変数 = (void)戻り値のある関数 #具体的な例としては下記一例を参照 と、ソースで書かれているものがあったのですが、 コメント等では、 「戻り値を明示しないときに(void)を付けて使用する」 と、書いてあります。 戻り値のある関数の前で(void)を付けると、戻り値が明示されなくなるのでしょうか?? または、このような動作にはならないのでしょうか。 自分自身、ソースの内容をうる覚えになっておりますので、 確認をしながらアップしていきたいと思いますので、 宜しくお願い致します。 /*一例*/ ・num1とnum2を足した値を返す int PlusPoint(int num1 , num2); ・PlusPointの値を格納する int Sum ◇ソース◆ #include <stdio.h> #include "Plus.h" int main(void) { int Sum; Sum = (void)PlusPoint; if(Sum == 2) { printf("false"); exit(0); } printf("true"); return 0; } *PlusPoint関数は外部で定義されている *プロトタイプ宣言はPlus.hに定義されいるものとする

  • C++で他のファイルの関数の引数を引きだす方法

    C++初心者です。 あるCプログラムに関数: testFunction(const char x[ ], int a, int b, int c)があり、 この関数はchar y[ ]を戻り値として返します。 次の段階で、別のC++を作成し、その中で、上記testFunctionを呼び出し、 使用している引数を引き出して以降のプログラムで使用する仕様のプログラムを組んでいます。 他のファイルに存在する関数を呼び出す方法は、 std::cout << testFunction(x[], a, b, c) << std::endl; ではないかと思っているのですが、ここから先が進まず困っている状況です。 戻り値だけではなく、引数も呼び出すことは可能でしょうか。 可能であれば、どのようにして呼び出すことができるのでしょうか。 アドバイスをお願いいたします。

  • cursesの呼び出し規約について

    cursesをはじめて使用したいのですが。 呼び出し規約でエラーが生じて利用することができません。 Windows7でvisual studioを用いています。 ある制御プログラムを書いているのですが、この場合では呼び出し規約を__stdcall (/Gz)に設定しています。 この呼び出し規約の条件でcursesを利用しようとすると以下のような LINK : warning LNK4098: defaultlib 'LIBCMT' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。 1>curses.obj : error LNK2001: 外部シンボル "_refresh@0" は未解決です。 エラーが出てきてしまいビルドすることができません。 用いているcursesのプログラムは以下のようなシンプルなものです。 #include <curses.h> int main() { initscr(); printw("Hello World !!!"); refresh(); getch(); endwin(); return 0; } 同じプログラムで呼び出し規約を__cdecl (/Gd)にしてあげるとうまくビルドができ実行することが可能なのですが、呼び出し規約を__cdecl (/Gd)に設定すると 某社(PCIボードを提供している会社です)の関数が使用できなくなってしまいます。 呼び出し規約を__stdcall (/Gz)でcursesを使用したいのですが。どのように改善すればよいのでしょうか?  アドバイスよろしくお願いします。

  • メモリ関連のエラーを取り除くには・・

    下記プログラムで、「.」区切りの文字列を 区切って返すプログラムを作成していますが、 メモリ関連のエラーが出てしまいます。 このようなメモリのエラーを取り除くには、何か 有用なツールでも使用すると楽になるのでしょうか。 自分で追いかけるのは大変なので・・ ちなみにmainの中で関数に渡したResultに結果が 入ってくるはずなのですが、mainの中で参照しようと するとエラーになってしまったので、bunkatu関数のなかで 表示するように一時的に変えております。 また、メモリの動的確保を行う場合には、同一のブロックで 行う必要があるのでしょうか。 #include <cstdlib> #include <iostream> using namespace std; int bunkatu (char *pOrg, int *iNum, char **Result); void main () { int iNum; char **Result = NULL; //結果格納用 bunkatu ("aaaa.fasdfafda.fa.dddd", &iNum, Result); } int bunkatu (char *pOrg, int *iNum, char **Result) { int iRtn; int iLocate = 0; int iTarget[10]; int iCount = 0; char *pTmp; pTmp = pOrg; if (*pTmp == '\0') { //空文字列の場合 iRtn = 1; } else { //空文字列以外の場合 //.を探す while (*pTmp != '\0') { //文字列終わりまで繰り返す。 if (*pTmp == '.') { //.が見つかった場合 iTarget[iCount] = iLocate; //.が見つかった添え字を保存 iCount++; //次の保存用にカウンタをカウントアップ } iLocate++; //詮索先を示すものをカウントアップ pTmp++; //詮索する位置を移動 } Result = (char **) calloc (iCount+1, sizeof (char *)); //切り出して表示 int iStart, iEnd; for (int j = 0; j < iCount+ 1; j++) { if (j == 0) { //はじめ iStart = 0; iEnd = iTarget[j] - 1; } else if(j < iCount){ //中間 iStart = iTarget[j - 1] + 1; iEnd = iTarget[j] - 1; } else if (j == iCount) { //最後 iStart = iTarget[j - 1] + 1; iEnd = strlen (pOrg) -1; } Result[j] = (char *) calloc (iEnd - iStart + 2, sizeof (char)); for (int k = 0; k < iEnd - iStart + 1; k++) { Result[j][k] = pOrg[iStart + k]; } Result[j][iEnd - iStart + 1] = '\0'; } *iNum = iCount; iRtn = 0; } //ちなみに~の部分 for (int i = 0; i < *iNum + 1 ; i++) { cout << Result[i] << endl; } for (int i = 0; i < *iNum + 1 ; i++) { free (Result[i]); } free (Result); return iRtn; }

専門家に質問してみよう