亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語(yǔ)言的語(yǔ)法風(fēng)格與代碼書(shū)寫(xiě)規(guī)范指南

 更新時(shí)間:2016年02月07日 15:07:39   投稿:goldensun  
這篇文章主要介紹了C語(yǔ)言的語(yǔ)法風(fēng)格與代碼書(shū)寫(xiě)規(guī)范指南,文中主張了一些諸如變量和結(jié)構(gòu)體的命名規(guī)范等細(xì)節(jié)方面的問(wèn)題,需要的朋友可以參考下

C代碼:

#include <stdio.h>
int main(void)
{
 printf("That is Right Style\n");
 return 0;
}

在一個(gè)標(biāo)準(zhǔn)的C語(yǔ)言程序中,最特殊的莫過(guò)于main函數(shù)了,而說(shuō)到底它就是一個(gè)函數(shù)而已,僅僅因?yàn)樗匚惶厥鈸碛械谝粓?zhí)行權(quán)力,換句話說(shuō),難道因?yàn)橐粋€(gè)人是省長(zhǎng)它就不是人類(lèi)了?所以函數(shù)該有的它都應(yīng)該有,那么函數(shù)還有什么呢?

函數(shù)大體上分為內(nèi)聯(lián)函數(shù)(C99)(內(nèi)聯(lián)函數(shù)并非C++專(zhuān)屬,C語(yǔ)言亦有,具體見(jiàn)前方鏈接)和非內(nèi)聯(lián)的普通函數(shù),它們之間有一個(gè)很明顯的特點(diǎn)(一般情況下),那就是不寫(xiě)原型直接在main函數(shù)上方定義,即使不加'inline'關(guān)鍵字,也能被編譯器默認(rèn)為內(nèi)聯(lián)函數(shù),但之后帶來(lái)的某些并發(fā)問(wèn)題就不是編譯器考慮的了。

普通函數(shù)正確的形式應(yīng)該為聲明與定義分離,聲明就是一個(gè)函數(shù)原型,函數(shù)原型應(yīng)該有一個(gè)函數(shù)名字,一個(gè)參數(shù)列表,一個(gè)返回值類(lèi)型和一個(gè)分號(hào)。定義就是函數(shù)的內(nèi)在,花括號(hào)內(nèi)的就是函數(shù)的定義:

//...
int function(int arg_1, float arg_2);
//...
int main(int argc, char* argv[])
{
 int output = function(11, 22.0);
 printf("%d\n",output);
 return 0;
}

int function(int arg_1, float arg_2)
{
 int return_value = arg_1;
 float temp_float = arg_2;
 return return_value;
} 

 
依上所述,當(dāng)非必要時(shí),在自己編寫(xiě)函數(shù)的時(shí)候請(qǐng)注意在開(kāi)頭(main函數(shù)之前)寫(xiě)上你的函數(shù)的原型,并且在末尾(main函數(shù)之后)寫(xiě)上你的函數(shù)定義,這是一個(gè)很好的習(xí)慣以及規(guī)范。所謂代碼整潔之道,就是如此。

函數(shù)的另一種分類(lèi)是,有返回值和無(wú)返回值,返回值的類(lèi)型可以是內(nèi)建(build-in)的也可以是自己定義的(struct, union之類(lèi)),無(wú)返回值則是void。

為什么我們十分譴責(zé)void main()這種寫(xiě)法?因?yàn)檫@完全是中國(guó)式教育延伸出來(lái)的譚式寫(xiě)法,main函數(shù)的返回值看似無(wú)用,實(shí)際上是由操作系統(tǒng)接收,在Windows操作系統(tǒng)下也許無(wú)甚"大礙"(實(shí)際上有),當(dāng)你使用Linux的過(guò)程中你會(huì)清晰的發(fā)現(xiàn)一個(gè)C語(yǔ)言程序的main返回值關(guān)系到一個(gè)系統(tǒng)是否能正常,高效的運(yùn)行,這里稍微提一句,0在Linux程序管道通信間代表著無(wú)錯(cuò)可行的意思。所以請(qǐng)扔掉void main這種寫(xiě)法。
為什么我們對(duì) main()這種省略返回值的寫(xiě)法置有微詞?能發(fā)明這種寫(xiě)法的人,必定是了解了,在C語(yǔ)言中,如果一個(gè)函數(shù)不顯式聲明自己的返回值,那么會(huì)被缺省認(rèn)為是int,但這一步是由編譯器掌控,然而C語(yǔ)言設(shè)計(jì)之初便是讓我們對(duì)一切盡可能的掌握,而一切不確定因子我們都不應(yīng)該讓它存在。其次有一個(gè)原則,能自己做的就不要讓編譯器做。

為什么我們對(duì)參數(shù)放空置有不滿(mǎn)(int main())?在C語(yǔ)言中,一個(gè)函數(shù)的參數(shù)列表有三種合法形態(tài):

 int function();
 int function(void);
 int function(int arg_n);
 int function(int arg_n, ...);

第一種代表?yè)碛形粗獋€(gè)參數(shù),第二種代表沒(méi)有參數(shù),第三種代表有一個(gè)參數(shù),第四種代表?yè)碛形粗獋€(gè)參數(shù),并且第一個(gè)參數(shù)類(lèi)型為int,未知參數(shù)在C語(yǔ)言中有一個(gè)解決方案就是,可變長(zhǎng)的參數(shù)列表,具體參考C標(biāo)準(zhǔn)庫(kù),在此我們解釋的依據(jù)就是,我們要將一切都掌控在自己的手中,我們不在括號(hào)內(nèi)填寫(xiě)參數(shù),代表著我們認(rèn)為一開(kāi)始的意思是它為空,正因此我們就應(yīng)該明確說(shuō)明它為void,而不該讓它成為一個(gè)未知參數(shù)長(zhǎng)度的函數(shù),如此在你不小心傳入?yún)?shù)的時(shí)候,編譯器也無(wú)法發(fā)現(xiàn)錯(cuò)誤。

int main(int argc, char* argv[]) 和 int main(void)才是我們?cè)搶?xiě)的C語(yǔ)言標(biāo)準(zhǔn)形式
對(duì)于縮進(jìn),除了編譯器提供的符號(hào)縮進(jìn)之外,我們可以自己給自己一個(gè)規(guī)范(請(qǐng)少用或者不用Tab),比如每一塊代碼相教上一個(gè)代碼塊有4格的縮進(jìn)。
對(duì)于學(xué)習(xí)C語(yǔ)言,請(qǐng)使用.c文件以及C語(yǔ)言編譯器練習(xí)以及編寫(xiě)C程序,請(qǐng)不要再使用C++的文件編寫(xiě)C語(yǔ)言程序,并且自圓其說(shuō)為了效率而使用C++的特性在C語(yǔ)言中,我們是祖國(guó)的下一代,是祖國(guó)的未來(lái),請(qǐng)不要讓自己毀在當(dāng)下,珍愛(ài)編程,遠(yuǎn)離清華大學(xué)出版社。

之所以如此敘述,并不是因?yàn)榍榫w,而是當(dāng)真如此,下方代碼:

 /*file: test.c*/
 #include <stdio.h>
 #define SIZES 5
 int main(void)
 {
  int* c_pointer = malloc(SIZES * sizeof(int));
  /*發(fā)生了一些事情*/
  free(c_pointer);
  return 0;
 }

這是一段標(biāo)準(zhǔn)的C語(yǔ)言程序,但是它能在C++個(gè)編譯器下編譯運(yùn)行嗎?換句話說(shuō)當(dāng)你將文件擴(kuò)展名由.c改為.cpp之后,它能編譯通過(guò)嗎?答案是不能。

為什么?答案是C++并不支持void*隱式轉(zhuǎn)換為其他類(lèi)型的指針,但是C語(yǔ)言允許。還有許許多多C于C++不相同的地方,興許有人說(shuō)C++是C的超集,但我并不這么認(rèn)為,一門(mén)語(yǔ)言的出現(xiàn)便有它的意義所在,關(guān)鍵在于我們?nèi)绾伟l(fā)揮它的最大優(yōu)勢(shì),而不是通過(guò)混淆概念來(lái)增強(qiáng)實(shí)用性。

程序式子的寫(xiě)法

一個(gè)人活在世界上,時(shí)時(shí)刻刻都注意著自己的言行舉止,而寫(xiě)程序也是如此,對(duì)于一個(gè)規(guī)范的能讓別人讀懂的程序而言,我們應(yīng)該盡可能減少阻礙因子,例如:

 int main(void)
 {int complex_int=100;
 int i,j,k,x;
 for(int temp=0;temp<complex_int;++temp){k=temp;
 x=k+complex_int;}
 printf(complex_int="%d is k=%d x=%d\n",complex_int,k,x);
 return 0;}

對(duì)于上述的代碼,我總是在班級(jí)里的同學(xué)手下出現(xiàn),但這段代碼除了讓別人困惑以外,自己在調(diào)試的時(shí)候也是十分不方便,每每遇到問(wèn)題了,即便IDE提示了在某處錯(cuò)誤,你也找不到問(wèn)題所在,經(jīng)常有人來(lái)問(wèn)我哪里錯(cuò)了,大部分情況都是少了分號(hào),括號(hào),或者作用域超過(guò),原因在哪?

要是一開(kāi)始將代碼寫(xiě)清楚了,這種情況簡(jiǎn)直是鳳毛麟角,想遇上都難。對(duì)于一個(gè)代碼而言,我們應(yīng)該注意讓其變得清晰。

等號(hào)兩邊使用空格:

 int complex_int = 100;

使用多個(gè)變量的聲明定義,或者函數(shù)聲明定義,函數(shù)使用時(shí),注意用空格分開(kāi)變量:

 int i, j, k, x;//但是十分不建議這么聲明難以理解意義的變量
 printf("complex_int = %d is k = %d x = %d\n", complex_int, k, x);
 void present(int arg_1, double arg_2);

對(duì)于一個(gè)清晰的程序而言,我們要讓每一個(gè)步驟清晰且有意義,這就要求我們?cè)诰帉?xiě)程序的時(shí)候盡量能讓代碼看起來(lái)結(jié)構(gòu)化,或者整體化。盡量讓每個(gè)程序式子為一行,如果有特別的需要讓多個(gè)式子寫(xiě)在同一行,可以使用,操作符進(jìn)行組合,但是會(huì)讓程序更難理解,日后調(diào)試的時(shí)候也更難發(fā)現(xiàn)錯(cuò)誤。

 /*Style 1*/ 
 for(int temp = 0;temp < complex_int;++temp)
 {
  k = temp;
  x = k + complex_int;
 }
 /*Style 2*/
 for(int temp = 0;temp < complex_int;++temp){
  k = temp;
  x = k + complex_int;
 }

對(duì)于上方的代碼,是C語(yǔ)言代碼花括號(hào)的兩種風(fēng)格,最好能選擇其中一種作為自己的編程風(fēng)格,這樣能讓你的程序看起來(lái)更加清晰,混合使用的利弊并不好說(shuō),關(guān)鍵還是看個(gè)人風(fēng)格。

對(duì)于作用域而言,在C語(yǔ)言中有一個(gè)經(jīng)常被使用的特例,當(dāng)一個(gè)條件語(yǔ)句,或者循環(huán)只有一條語(yǔ)句的時(shí)候,我們常常省略了花括號(hào){},而是僅僅使用一個(gè)分號(hào)作為結(jié)尾,這在很多情況下讓代碼不再啰嗦:

 if(pointo_int == NULL)
  fprintf(stderr, "The pointer is NULL!\n");
 else
 {
  printf("%d\n",*pointo_int);
  pointo_int = pointo_int->next;
 }

在這段代碼中if語(yǔ)句下方的代碼并沒(méi)有使用{}運(yùn)算符進(jìn)行指明,但是根據(jù)語(yǔ)法,該語(yǔ)句的確是屬于if語(yǔ)句的作用范圍內(nèi),如果我們此時(shí)寫(xiě)上了{(lán)}反而會(huì)令代碼看起來(lái)過(guò)于啰嗦。但是有的時(shí)候,這條特性并不是那么的有趣,當(dāng)使用嵌套功能的時(shí)候,還是建議使用{}進(jìn)行顯式的范圍規(guī)定,而不是使用默認(rèn)的作用域:

 for(int i = 0;i< 10;++i)
  for(int k = 0;k < 10;++k)
   while(flag != 1)
    set_value(arr[i][k]);

這段代碼,看起來(lái)十分簡(jiǎn)潔,但是確實(shí)是一個(gè)很大的隱患,當(dāng)我們要調(diào)試這段代碼的時(shí)候,總是需要修改它的構(gòu)造,而這就帶來(lái)了潛在的隱患。所以建議在使用嵌套的時(shí)候,無(wú)論什么情況,都能使用{}進(jìn)行包裝。

綜上所述,在開(kāi)始編寫(xiě)一個(gè)標(biāo)準(zhǔn)C語(yǔ)言程序的時(shí)候,請(qǐng)先把下面這些東西寫(xiě)上:

 #include <stdio.h>

 int main(void)
 {
  return 0;
 }


C代碼規(guī)范

命名

只要提到代碼規(guī)范,就不得不說(shuō)的一個(gè)問(wèn)題。
在一些小的演示程序中,也許費(fèi)盡心思去構(gòu)思一個(gè) 命名 是一件十分傻的行為,但是只要程序上升到你需要嚴(yán)正設(shè)計(jì),思考,復(fù)查的層次,你就需要好好考慮 命名 這個(gè)問(wèn)題。
函數(shù)命名:

C語(yǔ)言中,我們可以讓下劃線或者詞匯幫助我們表達(dá)函數(shù)功能:

前綴:

  • set 可以表示設(shè)置一個(gè)參數(shù)為某值
  • get 可以表示獲取某一個(gè)參數(shù)的值
  • is 可以表示詢(xún)問(wèn)是否是這種情況

后綴:

  • max/min 可以表示某種操作的最大(小)次數(shù)
  • cnt 可以表示當(dāng)前的操作次數(shù)
  • key 某種關(guān)鍵值
   size_t get_counts();
   size_t retry_max();
   int is_empty();

需要注意的只是,不要讓命名過(guò)于贅述其義,只簡(jiǎn)單保留動(dòng)作以及目的即可,詳細(xì)功能可以通過(guò)文檔來(lái)進(jìn)行進(jìn)一步的解釋。
結(jié)構(gòu)體命名:

由于結(jié)構(gòu)體的 標(biāo)簽,不會(huì)污染命名,即標(biāo)簽不在命名搜索范圍之內(nèi),所以可以放心使用:

有人習(xí)慣使用 typedef, 而有人喜歡使用 struct tag obj,后者比較多,但是前者也不失為一種好方法,仁者見(jiàn)仁智者見(jiàn)智。

  /*方法1*/
  struct inetaddr_4{
    int port;
    char * name;
  };
  struct inetaddr_4 *addr_info;
  /*方法2*/
  typedef struct _addr{
    int port;
    char * name;
  }inetaddr_4;
  inetaddr_4 *addr_info_2; 

 
兩者同處一個(gè)文件內(nèi)亦不會(huì)發(fā)生編譯錯(cuò)誤。
變量命名

  • 所有字符都使用小寫(xiě)
  • 含義多的可以用 _ 進(jìn)行輔助
  • 以 = 為標(biāo)準(zhǔn)進(jìn)行對(duì)齊
  • 類(lèi)型, 變量名左對(duì)齊。

等號(hào)左右兩端,最少有一個(gè)空格。

  int main(void)
  {
   int   counts = 0;
   inetaddr_4 *addr = NULL;

   return 0;
  }

為了防止指針聲明定義時(shí)候出錯(cuò),將 * 緊貼著變量名總不會(huì)出錯(cuò)。

  inetaddr_4 *addr, object, *addr_2;

其中 addr 和 addr_2 是指針,而 object 則是一個(gè)棧上的完整對(duì)象,并不是指針。

全局變量能少用就少用,必須要用的情況下,可以考慮添加前綴 g_

  int g_counts;

#define 命名

  • 所有字符都是用大寫(xiě),并用 _ 進(jìn)行分割。
  • 如果多于一個(gè)語(yǔ)句,使用 do{...}while(0) 進(jìn)行包裹,防止 ; 錯(cuò)誤。
  #define SWAP(x, y)  \
  do{      \
   x = x + y;  \
   y = x - y;   \
   x = x - y;   \
  }while(0)

當(dāng)然這個(gè)交換宏實(shí)際上有一點(diǎn)缺陷,在大后方會(huì)提出。此處是代碼規(guī)范,就不重復(fù)強(qiáng)調(diào)。

enum 命名

  • 所有字符都是用大寫(xiě),并用 _ 進(jìn)行分割
  • 與 define 相比,enum適用于同一類(lèi)型的常量聲明,而不是單一獨(dú)立的常量。往往出現(xiàn)都是成組。

格式化代碼

花括號(hào) {}

  • 混合使用符合節(jié)儉思想,但會(huì)稍微有一點(diǎn)結(jié)構(gòu)紊亂。
  • 單一使用能更好讓代碼結(jié)構(gòu)清晰。
  • 所謂混合,單一指的是是否一直使用 {} 進(jìn)行代碼包裹。
  • 有人認(rèn)為 當(dāng)單一語(yǔ)句的時(shí)候不必要添加 {},有的人則習(xí)慣添加
  • 當(dāng)作用域超過(guò)一個(gè)屏幕的時(shí)候,可以適當(dāng)?shù)氖褂米⑨寔?lái)指明 {} 作用域

     

while(1){
   if(tmp == NULL){
    break;
   }
   else if(fanny == 1){
    ... 大概超過(guò)了一個(gè)屏幕的代碼
   } /*else if fanny*/
  }/*end while*/

如果是代碼量少的情況下,但嵌套比較多,也可以使用這個(gè)方式進(jìn)行注釋。

括號(hào) ()

有人建議除了函數(shù)調(diào)用以外,在條件語(yǔ)句等類(lèi)似情況下使用 () 要在關(guān)鍵字后空一格,再接上 ()語(yǔ)句,對(duì)于這一點(diǎn),我個(gè)人習(xí)慣是不空格,但總有這種說(shuō)法。

  if (space == NULL) {
   /**TODO**/
  }
  while(1){
   /**我習(xí)慣于如此寫(xiě)**/
  }
  strcpy(str1, str2); /**第一種寫(xiě)法是為了和函數(shù)調(diào)用寫(xiě)法進(jìn)行區(qū)分**/
  return 0;
switch

一定要放一個(gè) default 在最后,即使它永遠(yuǎn)不會(huì)用到。
每個(gè) case 如果需要使用新變量,可以用 {} 包裹起來(lái),并在里面完成所有操作。

  switch(...)
  {
   case 1:
    /**TODO**/
    break;

   case 2:
   {
    int new_vari;
    /**創(chuàng)建新變量則用 {} 包裹起來(lái)**/
   }
   break;

   default:
    call_error();
  }

goto

雖然許多人,許多書(shū)都提醒不再使用 goto 關(guān)鍵字,而是使用 setjmp 和 longjmp來(lái)取代它,但是這還是那句話,仁者見(jiàn)仁智者見(jiàn)智,如果 goto 能夠讓代碼清晰,那何樂(lè)而不為呢,這個(gè)觀點(diǎn)也是最近才體會(huì)到的(并非我一己之言)。
具體使用可以查詢(xún)官方文檔。
語(yǔ)句

  • 應(yīng)該讓完整的語(yǔ)句在每一行中,只出現(xiàn)一次。
  • 對(duì)于變量聲明定義亦是如此
  • 原因是這樣能讓文檔更有針對(duì)性

頭文件保護(hù)

對(duì)于頭文件而言,在一個(gè)程序中有可能被多次包含(#include),如果缺少頭文件保護(hù),則會(huì)發(fā)生編譯錯(cuò)誤
不要將 _ 作為宏的開(kāi)頭或者結(jié)尾。

  #ifndef VECTOR_H_INCLUDE
   #define VECTOR_H_INCLUDE
    /**TODO**/
   #endif 

C語(yǔ)言的宏有諸多弊端,所以盡量使用 inline 函數(shù)來(lái)代替宏。在大后方會(huì)有解釋
但是,請(qǐng)不要因此拋棄了宏,比如在 C11 中有一個(gè)新興的宏。
變量

第一時(shí)刻初始化所有所聲明的變量,因?yàn)檫@么做總沒(méi)有壞處,而且能減少出錯(cuò)的可能。
函數(shù)

函數(shù)應(yīng)該盡可能的短小,一個(gè)ANSI屏幕的為最佳。
如果某個(gè)循環(huán)帶著空語(yǔ)句,使用 {} 進(jìn)行掛載,以免出現(xiàn)意外。

 while(*is_end++ != '\0')
 {
  ;
 }

雖然是空的循環(huán)體,但是寫(xiě)出來(lái)以免造成誤循環(huán)。

盡量不要讓函數(shù)返回值直接作為條件語(yǔ)句的判斷,這樣會(huì)極大降低可讀性

 if(is_eof(file) == 0)
  好過(guò)
 if(!is_eof(file))

不要為了方便或者一點(diǎn)點(diǎn)的所謂速度提升(也許根本沒(méi)有),而放棄可讀性,使用嵌入式的賦值語(yǔ)句

 int add = 10;
 int num = 11;
 int thr = 20;
 add = add + thr;
 num = add + 20;

      不要寫(xiě)成

 num = (add = add + thr) + 20;

浮點(diǎn)數(shù)

  • 萬(wàn)萬(wàn)記住不要再使用浮點(diǎn)數(shù)比較彼此是否相等或不等。
  • 如果把浮點(diǎn)數(shù)用在離散性的數(shù)據(jù)上,比如循環(huán)計(jì)數(shù)器,那就...

其他

使用 #if 而不是 #ifdef
可以使用 define() 來(lái)代替 #ifdef的功能

 #if !define(USERS_DEFINE)
  #define USERS_DEFINE ...
 #endif

對(duì)于某些大段需要消除的代碼,我們不能使用注釋 /**/,因?yàn)樽⑨尣荒軆?nèi)嵌著注釋(//除外),我們可以使用黑魔法:

 #if NOT_DECLARATION
  /**想要注釋的代碼**/
 #endif

不要使用純數(shù)字
意味著,不在使用毫無(wú)標(biāo)記的數(shù)字,因?yàn)榭赡苣氵^(guò)了幾個(gè)月再看源代碼的時(shí)候,你根本不知道這個(gè)數(shù)字代表著什么。
而應(yīng)該使用#define 給它一個(gè)名字,來(lái)說(shuō)明這個(gè)數(shù)字的意義。

相關(guān)文章

最新評(píng)論