奶头挺立呻吟高潮av全片,成人试看120秒体验区,性欧美极品v,A片高潮抽搐揉捏奶头视频

C語言關(guān)鍵字

時間:2025-05-26 15:00:49 好文 我要投稿
  • 相關(guān)推薦

C語言關(guān)鍵字

C語言關(guān)鍵字1

  一、皇帝身邊的小太監(jiān)----寄存器

  不知道什么是寄存器?那見過太監(jiān)沒有?沒有?其實我也沒有。沒見過不要緊,見過就麻煩大了。^_^,大家都看過古裝戲,那些皇帝們要閱讀奏章的時候,大臣總是先將奏章交給皇帝旁邊的小太監(jiān),小太監(jiān)呢再交給皇帝同志處理。這個小太監(jiān)只是個中轉(zhuǎn)站,并無別的功能。

  好,那我們再聯(lián)想到我們的CPU。CPU 不就是我們的皇帝同志么?大臣就相當(dāng)于我們的`內(nèi)存,數(shù)據(jù)從他這拿出來。那小太監(jiān)就是我們的寄存器了(這里先不考慮CPU 的高速緩存區(qū))。數(shù)據(jù)從內(nèi)存里拿出來先放到寄存器,然后CPU 再從寄存器里讀取數(shù)據(jù)來處理,處理完后同樣把數(shù)據(jù)通過寄存器存放到內(nèi)存里,CPU 不直接和內(nèi)存打交道。這里要說明的一點是:小太監(jiān)是主動的從大臣手里接過奏章,然后主動的交給皇帝同志,但寄存器沒這么自覺,它從不主動干什么事。一個皇帝可能有好些小太監(jiān),那么一個CPU 也可以有很多寄存器,不同型號的CPU 擁有寄存器的數(shù)量不一樣。

  為啥要這么麻煩啊?速度!就是因為速度。寄存器其實就是一塊一塊小的存儲空間,只不過其存取速度要比內(nèi)存快得多。進(jìn)水樓臺先得月嘛,它離CPU 很近,CPU 一伸手就拿到數(shù)據(jù)了,比在那么大的一塊內(nèi)存里去尋找某個地址上的數(shù)據(jù)是不是快多了?那有人問既然它速度那么快,那我們的內(nèi)存硬盤都改成寄存器得了唄。我要說的是:你真有錢!

  二、舉例

  register修飾符暗示編譯程序相應(yīng)的變量將被頻繁地使用,如果可能的'話,應(yīng)將其保存在CPU的寄存器中,以加快其存儲速度。例如下面的內(nèi)存塊拷貝代碼,

  #ifdef NOSTRUCTASSIGN

  memcpy (d, s, l)

  {

  register char *d;

  register char *s;

  register int i;

  while (i--)

  *d++ = *s++;

  }

  #endif

  三、使用register 修飾符的注意點

  但是使用register修飾符有幾點限制。

  首先,register變量必須是能被CPU所接受的類型。這通常意味著register變量必須是一個單個的值,并且長度應(yīng)該小于或者等于整型的長度。不過,有些機器的寄存器也能存放浮點數(shù)。

  其次,因為register變量可能不存放在內(nèi)存中,所以不能用“&”來獲取register變量的地址。

  由于寄存器的數(shù)量有限,而且某些寄存器只能接受特定類型的數(shù)據(jù)(如指針和浮點數(shù)),因此真正起作用的register修飾符的數(shù)目和類型都依賴于運行程序的機器,而任何多余的register修飾符都將被編譯程序所忽略。

  在某些情況下,把變量保存在寄存器中反而會降低程序的運行速度。因為被占用的寄存器不能再用于其它目的;或者變量被使用的.次數(shù)不夠多,不足以裝入和存儲變量所帶來的額外開銷。

  早期的C編譯程序不會把變量保存在寄存器中,除非你命令它這樣做,這時register修飾符是C語言的一種很有價值的補充。然而,隨著編譯程序設(shè)計技術(shù)的進(jìn)步,在決定那些變量應(yīng)該被存到寄存器中時,現(xiàn)在的C編譯環(huán)境能比程序員做出更好的決定。實際上,許多編譯程序都會忽略register修飾符,因為盡管它完全合法,但它僅僅是暗示而不是命令。

C語言關(guān)鍵字2

  為什么引入const?

  const 推出的初始目的,正是為了取代預(yù)編譯指令,消除它的缺點,同時繼承它的優(yōu)點。

  const關(guān)鍵字使用非常的靈活,這一點和php差別很大,php中const用來在類中定義一個常量,而在c中,const因位置不同有不同的作用,因情景不同有不同的角色,使用起來也是非常的靈活。

  (1):const用來修飾普通的.變量(指針變量除外)的時候,const type name 和 type const name 這兩種形式是完全等價的,都表示其是常量,不能進(jìn)行修改。

  #include

  int main(){

  const int num =23;

  printf("result=%dn",num);

  num =31;

  printf("result=%dn",num); //報錯,num是常量,不能修改

  }

  (2):const用來修飾指針變量的時候,分為以下四種情況

  1、const type *name :這種情況下,const修飾的指針變量name所指向的type類型對象,也就是說指向的這個對象是不能進(jìn)行修改的,因為其是常量,而指針變量確實可以進(jìn)行修改的

  #include

  int main(){

  int tmp = 23;

  const int *num = &tmp;

  printf("result=%dn",*num);

  (*num) = 24; //報錯,因為指針num指向的int類型的對象是不能進(jìn)行修改的

  printf("result=%dn",*num);

  }

  2、type const *name :這種情況下,const修飾的指針變量name所指向的type類型對象,意思完全同上,只是顛倒了以下順序。

  #include

  int main(){

  int tmp = 23;

  int const* num = &tmp;

  printf("result=%dn",*num);

  (*num) = 24; //報錯,因為指針num指向的int類型的對象是不能進(jìn)行修改的

  printf("result=%dn",*num);

  }

  3、type * const name :這種情況下,const修飾的指針變量name,也就是說這個指針變量的值是不能進(jìn)行修改的,但是指針變量所指向的對象確實可以修改的

  #include

  int main(){

  int tmp = 100;

  int *const num = &tmp;

  printf("result=%dn",*num);

  int change = 23;

  num = &change; //報錯,因為指針num是不能進(jìn)行修改的

  printf("result=%dn",*num);

  }

  4、const type * const name :這種情況下,const修飾的指針變量name以及指針變量name所指向的對象,也就是說這個指針變量以及這個指針變量所指向的對象都是不能進(jìn)行修改的

  (3):const在函數(shù)中的參數(shù)的作用:

  void get_value( const int num ){

  num=23; //報錯

  }

  調(diào)用get_value()函數(shù)的時候,傳遞num參數(shù)到函數(shù),因為定義了const,所以在函數(shù)中num是不能進(jìn)行修改的

C語言關(guān)鍵字3

  數(shù)據(jù)類型修飾相關(guān)

  auto按照自動的方式進(jìn)行變量的存儲

  const定義常量或常參數(shù)

  extern聲明外部變量或函數(shù)

  register指定變量的存儲類型是寄存器變量

  static指定變量的存儲類型是靜態(tài)變量,或指定函數(shù)是靜態(tài)函數(shù)

  volatile變量的`值可能在程序的外部被改變

  數(shù)據(jù)類型相關(guān)

  char字符型數(shù)據(jù)

  short定義短整型變量或指針

  int整型數(shù)據(jù)

  long長整型數(shù)據(jù)

  signed有符號的整型數(shù)據(jù)

  unsigned定義無符號的整型變量或數(shù)據(jù)

  float單精度浮點型數(shù)據(jù)

  double雙精度浮點型數(shù)據(jù)

  struct結(jié)構(gòu)體型數(shù)據(jù)

  enum枚舉型類型

  union聯(lián)合型數(shù)據(jù)

  void空型數(shù)據(jù)

  typedef為數(shù)據(jù)類型定義別名

  流程控制相關(guān)

  continue結(jié)束本次循環(huán)進(jìn)入下一次循環(huán)

  break跳出循環(huán)或switch語句

  switch定義switch語句

  case定義switch中的case子句

  default定義switch中的default子句

  do定義do-while語句

  while定義while或do-while語句

  if定義if語句或if-else語句

  else定義if-else語句

  for定義for循環(huán)語句

  goto定義goto語句

  預(yù)處理相關(guān)

  #include包含頭文件

  #define定義宏

  #undef取消已經(jīng)定義的宏

  #if定義條件編譯的條件

  #ifdef定義條件編譯的條件

  ifndef定義條件編譯的條件

  #elif定義條件編譯的條件

  #endif結(jié)束條件編譯

C語言關(guān)鍵字4

  通俗一點說: 枚舉就是你的那個變量就那么幾種狀態(tài),不會出現(xiàn)別的,而且你也不想被五一修改,那么就定義為枚舉好了。狀態(tài)機的狀態(tài),用這個表示最合適不過了。

  下面說一說枚舉和define的應(yīng)用場景

  兩enum是一個類型和變量了。

  define 只是一個宏定義

  define特點:

  優(yōu)點:宏定義可為多種類型的值,如字符串、整型、浮點型等。

  補充:其實他還可以用于各種函數(shù)替換,變量組合拼湊......這些是枚舉所無法達(dá)到的.。

  缺點:沒有范圍限制(全局范圍有效),容易發(fā)生沖突,產(chǎn)生不確定的結(jié)果;

  多個相關(guān)的值一起定義時比較散亂。

  enum特點:

  缺點:只能為整型值

  優(yōu)點:遵循范圍規(guī)則,不易和其它定義發(fā)生沖突。

  多個相關(guān)值一組,比較清晰。

  一般情況下二者可選時盡量用enum。

  再說一遍一般情況下二者可選時盡量用enum。

  另外debug的時候,枚舉變量顯示的數(shù)據(jù),是你的枚舉,調(diào)試很方便的。

C語言關(guān)鍵字5

  auto :聲明自動變量

  short :聲明短整型變量或函數(shù)

  int: 聲明整型變量或函數(shù)

  long :聲明長整型變量或函數(shù)

  float:聲明浮點型變量或函數(shù)

  double :聲明雙精度變量或函數(shù)

  char :聲明字符型變量或函數(shù)

  struct:聲明結(jié)構(gòu)體變量或函數(shù)

  union:聲明共用數(shù)據(jù)類型

  enum :聲明枚舉類型

  typedef:用以給數(shù)據(jù)類型取別名

  const :聲明只讀變量

  unsigned:聲明無符號類型變量或函數(shù)

  signed:聲明有符號類型變量或函數(shù)

  extern:聲明變量是在其他文件正聲明

  register:聲明寄存器變量

  static :聲明靜態(tài)變量

  volatile:說明變量在程序執(zhí)行中可被隱含地改變

  void :聲明函數(shù)無返回值或無參數(shù),聲明無類型指針

  if:條件語句

  else :條件語句否定分支(與 if 連用)

  switch :用于開關(guān)語句 case:開關(guān)語句分支

  for:一種循環(huán)語句

  do :循環(huán)語句的循環(huán)體

  while :循環(huán)語句的`循環(huán)條件

  goto:無條件跳轉(zhuǎn)語句

  continue:結(jié)束當(dāng)前循環(huán),開始下一輪循環(huán)

  break:跳出當(dāng)前循環(huán)

  default:開關(guān)語句中的“其他”分支

  sizeof:計算數(shù)據(jù)類型長度

  return :子程序返回語句(可以帶參數(shù),也可不帶參數(shù))循環(huán)條件

C語言關(guān)鍵字6

  要理解 restrict,先要知道什么是 Pointer aliasing。

  Pointer aliasing 是指兩個或以上的指針指向同一數(shù)據(jù),例如

  int i = 0;

  int *a = &i;

  int *b = &i;

  這樣會有什么問題呢?

  如果編譯器采用最安全的假設(shè),即不理會兩個指針會否指向同一數(shù)據(jù),那么通過指針讀寫數(shù)據(jù)是很直觀的。

  然而,這種假設(shè)會令編譯器無法優(yōu)化,例如:

  int foo(int *a, int *b)

  {

  *a = 5;

  *b = 6;

  return *a + *b; // 不一定是 11!

  }

  如果 a 和 b 都指向同一數(shù)據(jù),*b = 6 會導(dǎo)致 *a = 6,返回12。所以編譯器在做 *a + *b 的時候,需要重新讀取 *a 指向的數(shù)據(jù):

  foo:

  movl $5, (%rdi) # 存儲 5 至 *a

  movl $6, (%rsi) # 存儲 6 至 *b

  movl (%rdi), %eax # 重新讀取 *a (因為有可能被上一行指令造成改變)

  addl $6, %eax # 加上 6

  ret

  如果我們確保兩個指針不指向同一數(shù)據(jù),就可以用 restrict 修飾指針類型:

  int rfoo(int *restrict a, int *restrict b)

  {

  *a = 5;

  *b = 6;

  return *a + *b;

  }

  編譯器就可以根據(jù)這個信息,做出優(yōu)化:

  rfoo:

  movl $11, %eax # 在編譯期已計算出 11

  movl $5, (%rdi) # 存儲 5 至 *a

  movl $6, (%rsi) # 存儲 6 至 *b

  ret

  但如果用了 restrict 去修飾兩個指針,而它們在作用域內(nèi)又指向同一地址,那么是未定義行為。

  總括而言,restrict 是為了告訴編譯器額外信息(兩個指針不指向同一數(shù)據(jù)),從而生成更優(yōu)化的'機器碼。注意,編譯器是無法自行在編譯期檢測兩個指針是否 alias。如使用 restrict,程序員也要遵守契約才能得出正確的代碼(指針不能指向相同數(shù)據(jù))。

  以個人經(jīng)驗而言,編寫代碼時通常會忽略 pointer aliasing 的問題。更常見是在性能剖測時,通過反編譯看到很多冗余的讀取指令,才會想到加入 restrict 關(guān)鍵字來提升性能。

C語言關(guān)鍵字7

  A循環(huán)語句:

  for:一種循環(huán)語句

  do :循環(huán)語句的循環(huán)體

  while :循環(huán)語句的.循環(huán)條件

  break:跳出當(dāng)前循環(huán)

  continue:結(jié)束當(dāng)前循環(huán),開始下一輪循環(huán) B條件語句:

  if: 條件語句

  else:條件語句否定分支(與 if 連用)

  goto:無條件跳轉(zhuǎn)語句 C開關(guān)語句:

  switch :用于開關(guān)語句

  case:開關(guān)語句分支

  default:開關(guān)語句中的“其他”分支 D返回語句:

  return :子程序返回語句(可以帶參數(shù),也看不帶參數(shù))

C語言關(guān)鍵字8

  (1) char :聲明字符型變量或函數(shù)

  (2) double :聲明雙精度變量或函數(shù)

  (3) enum :聲明枚舉類型

  (4) float:聲明浮點型變量或函數(shù)

  (5) int: 聲明整型變量或函數(shù)

  (6) long :聲明長整型變量或函數(shù)

  (7) short :聲明短整型變量或函數(shù)

  (8) signed:聲明有符號類型變量或函數(shù)

  (9) struct:聲明結(jié)構(gòu)體變量或函數(shù)

  (10) union:聲明共用體(聯(lián)合)數(shù)據(jù)類型

  (11) unsigned:聲明無符號類型變量或函數(shù)

  (12) void :聲明函數(shù)無返回值或無參數(shù),聲明無類型指針

C語言關(guān)鍵字9

  因為在app開發(fā)中,定義網(wǎng)絡(luò)鏈接或者設(shè)定常用變量時經(jīng)常會用到一些C中的`關(guān)鍵字,但很多同學(xué)只見其名而不知其意,今天就介紹2個開發(fā)中常用的C語言關(guān)鍵字,分別是C語言中的static和extern關(guān)鍵字。

  1.static

  static的.作用

  修飾局部變量:

  1.延長局部變量的生命周期,程序結(jié)束才會銷毀

  2.局部變量只會生成一份內(nèi)存,只會初始化一次

  3.改變局部變量的作用域

  寫法:

  //方法內(nèi)部static修飾的變量

  //不管調(diào)用與否,只會調(diào)用一次

  - (void)staticTest

  {

  // static修飾局部變量

  static int age = 0;

  age++;

  NSLog(@"%d",age);

  }

  //即調(diào)用兩次該方法

  //打印結(jié)果

  //1

  //2

  修飾全局變量

  1.只能在本文件中訪問,修改全局變量的作用域,生命周期不會改

  2.避免重復(fù)定義全局變量

  寫法:

  // 全局變量:只有一份內(nèi)存,

  //所有文件共享,與extern聯(lián)合使用。

  // 寫在方法外部

  // static修飾全局變量

  static int age = 20;

  //調(diào)用

  extern int age;

  NSLog(@"%d",age);

  //打印結(jié)果

  //20

  2.extern

  extern作用:

  只是用來獲取全局變量(包括全局靜態(tài)變量)的值,不能用于定義變量

  extern工作原理:

  先在當(dāng)前文件查找有沒有全局變量,沒有找到,才會去其他文件查找。

C語言關(guān)鍵字10

  標(biāo)識符

  定義變量時,我們使用了諸如“a”“abc”“mn123”這樣的名字,它們都是程序員自己起的,一般能夠表達(dá)出變量的作用,這叫做標(biāo)識符(Identifier)。

  標(biāo)識符就是程序員自己起的名字,除了變量名,后面還會講到函數(shù)名、宏名、結(jié)構(gòu)體名等。不過,名字也不能隨便起,C語言規(guī)定,標(biāo)識符只能由字母(A~Z, a~z)、數(shù)字(0~9)和下劃線(_)組成,并且第一個字符必須是字母或下劃線。

  以下標(biāo)識符是合法的:

  a, x, x3, BOOK_1, sum5

  以下標(biāo)識符是非法的:

  3s 不能以數(shù)字開頭

  s*T 出現(xiàn)非法字符*

  -3x 不能以減號(-)開頭

  bowy-1 出現(xiàn)非法字符減號(-)

  在使用標(biāo)識符時還必須注意以下幾點:

  C語言雖然不限制標(biāo)識符的長度,但是它受到不同編譯器的限制,同時也受到具體機器的限制。例如在某個編譯器中規(guī)定標(biāo)識符前128位有效,當(dāng)兩個標(biāo)識符前128位相同時,則被認(rèn)為是同一個標(biāo)識符。

  在標(biāo)識符中,大小寫是有區(qū)別的,例如BOOK和book 是兩個不同的標(biāo)識符。

  標(biāo)識符雖然可由程序員隨意定義,但標(biāo)識符是用于標(biāo)識某個量的符號,因此,命名應(yīng)盡量有相應(yīng)的意義,以便于閱讀理解,作到“顧名思義”。

  關(guān)鍵字

  關(guān)鍵字(Keywords)是由C語言規(guī)定的具有特定意義的字符串,通常也稱為保留字,例如 int、char、long、float、unsigned 等。我們定義的標(biāo)識符不能與關(guān)鍵字相同,否則會出現(xiàn)錯誤。

  你也可以將關(guān)鍵字理解為具有特殊含義的標(biāo)識符,它們已經(jīng)被系統(tǒng)使用,我們不能再使用了。

  標(biāo)準(zhǔn)C語言中一共規(guī)定了32個關(guān)鍵字,大家可以參考C語言關(guān)鍵字及其解釋[共32個],后續(xù)我們會一一講解。

  注釋

  注釋(Comments)可以出現(xiàn)在代碼中的.任何位置,用來向用戶提示或解釋程度的意義。程序編譯時,會忽略注釋,不做任何處理,就好像它不存在一樣。

  C語言支持單行注釋和多行注釋:

  單行注釋以//開頭,直到本行末尾(不能換行);

  多行注釋以/*開頭,以*/結(jié)尾,注釋內(nèi)容可以有一行或多行。

  一個使用注釋的例子:

  /* Powered by: c.biancheng.net Author: xiao p Date: 20xx-6-26*/#includeint main(){ /* puts 會在末尾自動添加換行符 */ puts("http://c.biancheng.net"); printf("C語言中文網(wǎng)"); //printf要手動添加換行符 return 0;}

  運行結(jié)果:

  http://c.biancheng.net

  C語言中文網(wǎng)

  在調(diào)試程序的過程中可以將暫時不使用的語句注釋掉,使編譯器跳過不作處理,待調(diào)試結(jié)束后再去掉注釋。

  需要注意的是,多行注釋不能嵌套使用。例如下面的注釋是錯誤的:

  /*C語言/*中文*/網(wǎng)*/

  而下面的注釋是正確的:

  /*C語言中文網(wǎng)*/ /*c.biancheng.net*/

C語言關(guān)鍵字11

  const 我們稱之為常量修飾符,意即其所修飾的對象為常量(immutable)。

  我們來分情況看語法上它該如何被使用。

  1、函數(shù)體內(nèi)修飾局部變量。

  例:

  void func(){

  const int a=0;

  }

  首先,我們先把const這個單詞忽略不看,那么a是一個int類型的局部自動變量,

  我們給它賦予初始值0。

  然后再看const.

  const作為一個類型限定詞,和int有相同的地位。

  const int a;

  int const a;

  是等價的。于是此處我們一定要清晰的明白,const修飾的對象是誰,是a,和int沒

  有關(guān)系。const 要求他所修飾的對象為常量,不可被改變,不可被賦值,不可作為左值(l-value)。

  這樣的寫法也是錯誤的。

  const int a;

  a=0;

  這是一個很常見的使用方式:

  const double pi=3.14;

  在程序的后面如果企圖對pi再次賦值或者修改就會出錯。

  然后看一個稍微復(fù)雜的例子。

  const int* p;

  還是先去掉const 修飾符號。

  注意,下面兩個是等價的。

  int* p;

  int *p;

  其實我們想要說的是,*p是int類型。那么顯然,p就是指向int的指針。

  同理

  const int* p;

  其實等價于

  const int (*p);

  int const (*p);

  即,*p是常量。也就是說,p指向的數(shù)據(jù)是常量。

  于是

  p+=8; //合法

  *p=3; //非法,p指向的數(shù)據(jù)是常量。

  那么如何聲明一個自身是常量指針呢?方法是讓const盡可能的`靠近p;

  int* const p;

  const右面只有p,顯然,它修飾的是p,說明p不可被更改。然后把const去掉,可以

  看出p是一個指向 int形式變量的指針。

  于是

  p+=8; //非法

  *p=3; //合法

  再看一個更復(fù)雜的例子,它是上面二者的綜合

  const int* const p;

  說明p自己是常量,且p指向的變量也是常量。

  于是

  p+=8; //非法

  *p=3; //非法

  const 還有一個作用就是用于修飾常量靜態(tài)字符串。

  例如:

  const char* name=David;

  如果沒有const,我們可能會在后面有意無意的寫name[4]='x'這樣的語句,這樣會

  導(dǎo)致對只讀內(nèi)存區(qū)域的賦值,然后程序會立刻異常終止。有了 const,這個錯誤就

  能在程序被編譯的時候就立即檢查出來,這就是const的好處。讓邏輯錯誤在編譯

  期被發(fā)現(xiàn)。

  const 還可以用來修飾數(shù)組

  const char s[]=David;

  與上面有類似的作用。

  2、在函數(shù)聲明時修飾參數(shù)

  來看實際中的一個例子。

  void * memmove(void *dst, const void *src, size_t len);

  這是標(biāo)準(zhǔn)庫中的一個函數(shù),用于按字節(jié)方式復(fù)制字符串(內(nèi)存)。

  它的第一個參數(shù),是將字符串復(fù)制到哪里去(dest),是目的地,這段內(nèi)存區(qū)域必須

  是可寫。

  它的第二個參數(shù),是要將什么樣的字符串復(fù)制出去,我們對這段內(nèi)存區(qū)域只做讀

  取,不寫。

  于是,我們站在這個函數(shù)自己的角度來看,src 這個指針,它所指向的內(nèi)存內(nèi)所存

  儲的數(shù)據(jù)在整個函數(shù)執(zhí)行的過程中是不變。于是src所指向的內(nèi)容是常量。于是就

  需要用const修飾。

  例如,我們這里這樣使用它。

  const char* s=hello;

  char buf[100];

  memmove(buf,s,6); //這里其實應(yīng)該用strcpy或memcpy更好

  如果我們反過來寫,

  memmove(s,buf,6);

  那么編譯器一定會報錯。事實是我們經(jīng)常會把各種函數(shù)的參數(shù)順序?qū)懛础J聦嵤蔷?/p>

  譯器在此時幫了我們大忙。如果編譯器靜悄悄的不報錯,(在函數(shù)聲明處去掉

  const即可),那么這個程序在運行的時候一定會崩潰。

  這里還要說明的一點是在函數(shù)參數(shù)聲明中const一般用來聲明指針而不是變量本身。

  例如,上面的size_t len,在函數(shù)實現(xiàn)的時候可以完全不用更改len的值,那么是否

  應(yīng)該把len也聲明為常量呢?可以,可以這么做。我們來分析這么做有什么優(yōu)劣。

  如果加了const,那么對于這個函數(shù)的實現(xiàn)者,可以防止他在實現(xiàn)這個函數(shù)的時候修

  改不需要修改的值(len),這樣很好。

  但是對于這個函數(shù)的使用者,

  1。這個修飾符號毫無意義,我們可以傳遞一個常量整數(shù)或者一個非常量整數(shù)過

  去,反正對方獲得的只是我們傳遞的一個copy。

  2。暴露了實現(xiàn)。我不需要知道你在實現(xiàn)這個函數(shù)的時候是否修改過len的值。

  所以,const一般只用來修飾指針。

  再看一個復(fù)雜的例子

  int execv(const char *path, char *const argv[]);

  著重看后面這個,argv.它代表什么。

  如果去掉const,我們可以看出

  char * argv[];

  argv是一個數(shù)組,它的每個元素都是char *類型的指針。

  如果加上const.那么const修飾的是誰呢?他修飾的是一個數(shù)組,argv[],意思就是

  說這個數(shù)組的元素是只讀的。那么數(shù)組的元素的是什么類型呢?是char *類型的指

  針.也就是說指針是常量,而它指向的數(shù)據(jù)不是。

  于是

  argv[1]=NULL; //非法

  argv[0][0]='a'; //合法

  3、全局變量。

  我們的原則依然是,盡可能少的使用全局變量。

  我們的第二條規(guī)則 則是,盡可能多的使用const。

  如果一個全局變量只在本文件中使用,那么用法和前面所說的函數(shù)局部變量沒有什

  么區(qū)別。

  如果它要在多個文件間共享,那么就牽扯到一個存儲類型的問題。

  有兩種方式。

  1.使用extern

  例如

  /* file1.h */

  extern const double pi;

  /* file1.c */

  const double pi=3.14;

  然后其他需要使用pi這個變量的,包含file1.h

  #include file1.h

  或者,自己把那句聲明復(fù)制一遍就好。

  這樣做的結(jié)果是,整個程序鏈接完后,所有需要使用pi這個變量的共享一個存儲區(qū)域。

  最后,說說const的作用。

  const 的好處,是引入了常量的概念,讓我們不要去修改不該修改的內(nèi)存。直接的

  作用就是讓更多的邏輯錯誤在編譯期被發(fā)現(xiàn)。所以我們要盡可能的多使用const。

  但是很多人并不習(xí)慣使用它,更有甚者,是在整個程序 編寫/調(diào)試 完后才補

  const。如果是給函數(shù)的聲明補const,尚好。如果是給 全局/局部變量補const,那

  么……那么,為時已晚,無非是讓代碼看起來更漂亮了。

C語言關(guān)鍵字12

  其實在寫代碼的時候,關(guān)鍵字還是用的比較多的,這里主要就平常中用到的常用關(guān)鍵字進(jìn)行總結(jié),便于更全面的理解其在代碼中的意圖。下文主要介紹C語言的關(guān)鍵字define的相關(guān)內(nèi)容。

  1 、防止一個頭文件被重復(fù)包含

  當(dāng)我們的程序很大很大時,比如超過20000行時,我們很可能沒有辦法對所有的文件都有清楚的了解,特別是.h

  文件,那么我們怎么做才能避免include時重復(fù)包含呢 答案就是#define

  如下:

  a.h b.h c.h 三個文件

  a.h 內(nèi)容

  int variable_a;

  b.h 內(nèi)容

  #include "a.h"

  int variable_b;

  c.h內(nèi)容

  #include "a.h"

  #include "b.h"

  int c;

  那么c.h就包含了兩次a.h,那如何避免呢

  #ifndef A_H

  #define A_H

  //頭文件A

  #endif

  這樣就可以保證a.h只會被包含一次

  2、簡單替換

  #define MACRO_A 15

  后面出現(xiàn)的MACRO_A 都會被替換為15這個數(shù)

  3、帶參數(shù)的替換

  #define ABS( a ) ( ((a)>0) ? (a) : (-(a)) )

  可以使用宏替換來實現(xiàn)簡單的`函數(shù)。

  以下是#define的高級用法

  4、高級用法

  define中的三個特殊符號:#,##,#@

  #defineConn(x,y) x##y

  #defineToChar(x) #@x

  #defineToString(x) #x

  (1)x##y表示什么?表示x連接y,舉例說:

  intn=Conn(123,456);/* 結(jié)果就是n=123456;*/

  char*str=Conn("asdf","adf");/*結(jié)果就是 str = "asdfadf";*/

  (2)再來看#@x,其實就是給x加上單引號,結(jié)果返回是一個const char。舉例說:

  char a = ToChar(1);結(jié)果就是a='1';

  做個越界試驗char a = ToChar(123);結(jié)果就錯了;

  但是如果你的參數(shù)超過四個字符,編譯器就給給你報錯了!

  error C20xx: too many characters in constant :P

  (3)最后看看#x,估計你也明白了,他是給x加雙引號

  char* str = ToString(123132);就成了str="123132";

C語言關(guān)鍵字13

  1.作用于變量:

  用static聲明局部變量-------局部變量指在代碼塊{}內(nèi)部定義的變量,只在代碼塊內(nèi)部有效(作用域),其缺省的存儲方式是自動變量或說是動態(tài) 存儲的,即指令執(zhí)行到變量定義處時才給變量分配存儲單元,跳出代碼塊時釋放內(nèi)存單元(生命期)。用static聲明局部變量時,則改變變量的存儲方式(生 命期),使變量成為靜態(tài)的局部變量,即編譯時就為變量分配內(nèi)存,直到程序退出才釋放存儲單元。這樣,使得該局部變量有記憶功能,可以記憶上次的數(shù)據(jù),不過 由于仍是局部變量,因而只能在代碼塊內(nèi)部使用(作用域不變)。

  用static聲明外部變量-------外部變量指在所有代碼塊{}之外定義的變量,它缺省為靜態(tài)變量,編譯時分配內(nèi)存,程序結(jié)束時釋放內(nèi) 存單元。同時其作用域很廣,整個文件都有效甚至別的文件也能引用它。為了限制某些外部變量的作用域,使其只在本文件中有效,而不能被其他文件引用,可以用 static關(guān)鍵字對其作出聲明。

  總結(jié):用static聲明局部變量,使其變?yōu)殪o態(tài)存儲方式(靜態(tài)數(shù)據(jù)區(qū)),作用域不變;用static聲明外部變量,其本身就是靜態(tài)變量,這只會改變其連接方式,使其只在本文件內(nèi)部有效,而其他文件不可連接或引用該變量。

  2.作用于函數(shù):

  使用static用于函數(shù)定義時,對函數(shù)的連接方式產(chǎn)生影響,使得函數(shù)只在本文件內(nèi)部有效,對其他文件是不可見的。這樣的函數(shù)又叫作靜態(tài)函數(shù)。使用靜態(tài)函數(shù)的好處是,不用擔(dān)心與其他文件的同名函數(shù)產(chǎn)生干擾,另外也是對函數(shù)本身的一種保護機制。

  如果想要其他文件可以引用本地函數(shù),則要在函數(shù)定義時使用關(guān)鍵字extern,表示該函數(shù)是外部函數(shù),可供其他文件調(diào)用。另外在要引用別的文件中定義的外部函數(shù)的文件中,使用extern聲明要用的外部函數(shù)即可。

  const作用: “只讀(readonly)”

  1.定義常量

  (1)const

  修飾變量,以下兩種定義形式在本質(zhì)上是一樣的。它的含義是:const修飾的類型為TYPE的變量value是不可變的,readonly。

  TYPE const ValueName = value;

  const TYPE ValueName = value;

  (2)將const改為外部連接,作用于擴大至全局,編譯時會分配內(nèi)存,并且可以不進(jìn)行初始化,僅僅作為聲明,編譯器認(rèn)為在程序其他地方進(jìn)行了定義.

  extend const int ValueName = value;

  2.指針使用CONST

  (1)指針本身是常量不可變

  char * const pContent;

  const (char*) pContent;

  (2)指針?biāo)赶虻膬?nèi)容是常量不可變

  const char *pContent;

  char const *pContent;

  (3)兩者都不可變

  const char* const pContent;

  (4)還有其中區(qū)別方法,沿著*號劃一條線:如果const位于*的左側(cè),則const就是用來修飾指針?biāo)赶虻淖兞浚粗羔樦赶驗槌A?如果const位于*的右側(cè),const就是修飾指針本身,即指針本身是常量。

  3.函數(shù)中使用CONST

  (1)const修飾函數(shù)參數(shù)

  a.傳遞過來的參數(shù)在函數(shù)內(nèi)不可以改變(無意義,因為Var本身就是形參)

  void function(const int Var);

  b.參數(shù)指針?biāo)竷?nèi)容為常量不可變

  void function(const char* Var);

  c.參數(shù)指針本身為常量不可變(也無意義,因為char* Var也是形參)

  void function(char* const Var);

  d.參數(shù)為引用,為了增加效率同時防止修改。修飾引用參數(shù)時:

  void function(const Class& Var); //引用參數(shù)在函數(shù)內(nèi)不可以改變

  void function(const TYPE& Var); //引用參數(shù)在函數(shù)內(nèi)為常量不可變

  這樣的一個const引用傳遞和最普通的函數(shù)按值傳遞的效果是一模一樣的.,他禁止對引用的對象的一切修改,唯一不同的是按值傳遞會先建立一個類對象的副本, 然后傳遞過去,而它直接傳遞地址,所以這種傳遞比按值傳遞更有效.另外只有引 用的const傳遞可以傳遞一個臨時對象,因為臨時對象都是const屬性, 且是不可見的,他短時間存在一個局部域中,所以不能使用指針,只有引用的 const傳遞能夠捕捉到這個家伙.

  (2)const 修飾函數(shù)返回值

  const修飾函數(shù)返回值其實用的并不是很多,它的含義和const修飾普通變量以及指針的含義基本相同。

  a.

  const int fun1() //這個其實無意義,因為參數(shù)返回本身就是賦值。

  b.

  const int * fun2() //調(diào)用時

  const int *pValue = fun2(); //我們可以把fun2()看作成一個變量,即指針內(nèi)容不可變。

  c.

  int* const fun3() //調(diào)用時

  int * const pValue = fun2(); //我們可以把fun2()看作成一個變量,即指針本身不可變。

C語言關(guān)鍵字14

  1、static 修飾函數(shù)

  函數(shù)的訪問范圍就被限定在本文件以內(nèi),任何本文件以外內(nèi)容的訪問此函數(shù),都是非法和無效的,編譯不會通過,提示找不到該符號。 所以,我們在進(jìn)行一個函數(shù)設(shè)計的時候,首先需要考慮的就是,這個函數(shù)的作用是什么,作用范圍是什么,我們應(yīng)該怎么去保證模塊化。如果沒有被外部文件訪問,那么就把它限定為static。這就是這個static 修飾函數(shù)的用處。

  2、static 修飾變量

  無論在文件的哪個位置,用static修飾 變量,這個變量運行時都是占用的'RAM里的靜態(tài)全局?jǐn)?shù)據(jù)區(qū),再說一遍,靜態(tài)全局。在程序運行的整個生命周期內(nèi)是不會釋放的,這個我們也在前面單片機相關(guān)的文章里講過了。

  既然static 修飾的變量和全局變量占用一樣的空間,為何還有static修飾,直接全局變量也就OK了啊? 對于硬件來說,有沒有static自然是一樣的,但是對于軟件卻不一樣。

  函數(shù)外static修飾的變量,僅僅限定與本文件使用,所以你可以不關(guān)注本文件以外的信息,就知道這個變量是如何變化和使用的,這就減小了你閱讀程序的難度。

  函數(shù)內(nèi)static修飾的變量,僅僅限定于本函數(shù)使用,所以你可以不關(guān)注本函數(shù)以外的信息,就知道這個變量是如何變化的,進(jìn)一步減小了你閱讀程序的難度,也方便查詢問題。

  所以能定義為static的就盡量定義為static(后面會再更新如何去除static,書寫可重入函數(shù))。

C語言關(guān)鍵字15

  1.static關(guān)鍵字

  這個關(guān)鍵字的作用是餓很難強大的。

  要對static關(guān)鍵字深入了解,首先需要掌握標(biāo)準(zhǔn)C程序的組成。

  標(biāo)準(zhǔn)C程序一直由下列部分組成:

  1)正文段——CPU執(zhí)行的機器指令部分,也就是你的程序。一個程序只有一個副本;只讀,這是為了防止程序由于意外事故而修改自身指令;

  2)初始化數(shù)據(jù)段(數(shù)據(jù)段)——在程序中所有賦了初值的全局變量,存放在這里。

  3)非初始化數(shù)據(jù)段(bss段)——在程序中沒有初始化的全局變量;內(nèi)核將此段初始化為0。

  注意:只有全局變量被分配到數(shù)據(jù)段中。

  4)棧——增長方向:自頂向下增長;自動變量以及每次函數(shù)調(diào)用時所需要保存的信息(返回地址;環(huán)境信息)。這句很關(guān)鍵,常常有筆試題會問到什么東西放到棧里面就足以說明。

  5)堆——動態(tài)存儲分配。

  在嵌入式C語言當(dāng)中,它有三個作用:

  作用一:在函數(shù)體,一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。

  這樣定義的變量稱為局部靜態(tài)變量:在局部變量之前加上關(guān)鍵字static,局部變量就被定義成為一個局部靜態(tài)變量。也就是上面的作用一中提到的在函數(shù)體內(nèi)定義的變量。除了類型符外,若不加其它關(guān)鍵字修飾,默認(rèn)都是局部變量。比如以下代碼:

  void test1(void)

  {

  unsigned char a;

  static unsigned char b;

  …

  a++;

  b++;

  }

  在這個例子中,變量a是局部變量,變量b為局部靜態(tài)變量。作用一說明了局部靜態(tài)變量b的特性:在函數(shù)體,一個被聲明為靜態(tài)的變量(也就是局部靜態(tài)變量)在這一函數(shù)被調(diào)用過程中維持其值不變。這句話什么意思呢?若是連續(xù)兩次調(diào)用上面的函數(shù)test1:

  void main(void)

  {

  …

  test1();

  test1();

  …

  }

  然后使程序暫停下來,讀取a和b的值,你會發(fā)現(xiàn),a=1,b=2。怎么回事呢,每次調(diào)用test1函數(shù),局部變量a都會重新初始化為0x00;然后執(zhí)行a++;而局部靜態(tài)變量在調(diào)用過程中卻能維持其值不變。

  通常利用這個特性可以統(tǒng)計一個函數(shù)被調(diào)用的次數(shù)。

  聲明函數(shù)的一個局部變量,并設(shè)為static類型,作為一個計數(shù)器,這樣函數(shù)每次被調(diào)用的時候就可以進(jìn)行計數(shù)。這是統(tǒng)計函數(shù)被調(diào)用次數(shù)的最好的辦法,因為這個變量是和函數(shù)息息相關(guān)的.,而函數(shù)可能在多個不同的地方被調(diào)用,所以從調(diào)用者的角度來統(tǒng)計比較困難。代碼如下:

  void count();

  int main()

  {

  int i;

  for (i = 1; i <= 3; i++)

  {

  count();

  {

  return 0;

  }

  void count()

  {

  static num = 0;

  num++;

  printf(" I have been called %d",num,"times/n");

  }

  輸出結(jié)果為:

  I have been called 1 times.

  I have been called 2 times.

  I have been called 3 times.

  看一下局部靜態(tài)變量的詳細(xì)特性,注意它的作用域。

  1)內(nèi)存中的位置:靜態(tài)存儲區(qū)

  2)初始化:未經(jīng)初始化的全局靜態(tài)變量會被程序自動初始化為0(自動對象的值是任意的,除非他被顯示初始化)

  3)作用域:作用域仍為局部作用域,當(dāng)定義它的函數(shù)或者語句塊結(jié)束的時候,作用域隨之結(jié)束。

  注:當(dāng)static用來修飾局部變量的時候,它就改變了局部變量的存儲位置,從原來的棧中存放改為靜態(tài)存儲區(qū)。但是局部靜態(tài)變量在離開作用域之后,并沒有被銷毀,而是仍然駐留在內(nèi)存當(dāng)中,直到程序結(jié)束,只不過我們不能再對他進(jìn)行訪問。

  作用二:在模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。

  這樣定義的變量也稱為全局靜態(tài)變量:在全局變量之前加上關(guān)鍵字static,全局變量就被定義成為一個全局靜態(tài)變量。也就是上述作用二中提到的在模塊內(nèi)(但在函數(shù)體外)聲明的靜態(tài)變量。

  定義全局靜態(tài)變量的好處:

  <1>不會被其他文件所訪問,修改,是一個本地的局部變量。

  全局變量的詳細(xì)特性,注意作用域,可以和局部靜態(tài)變量相比較:

  1)內(nèi)存中的位置:靜態(tài)存儲區(qū)(靜態(tài)存儲區(qū)在整個程序運行期間都存在)

  2)初始化:未經(jīng)初始化的全局靜態(tài)變量會被程序自動初始化為0(自動對象的值是任意的,除非他被顯示初始化)

  3)作用域:全局靜態(tài)變量在聲明他的文件之外是不可見的。準(zhǔn)確地講從定義之處開始到文件結(jié)尾。

  當(dāng)static用來修飾全局變量的時候,它就改變了全局變量的作用域(在聲明他的文件之外是不可見的),但是沒有改變它的存放位置,還是在靜態(tài)存儲區(qū)中。

  作用三:在模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。

  這樣定義的函數(shù)也成為靜態(tài)函數(shù):在函數(shù)的返回類型前加上關(guān)鍵字static,函數(shù)就被定義成為靜態(tài)函數(shù)。函數(shù)的定義和聲明默認(rèn)情況下是extern的,但靜態(tài)函數(shù)只是在聲明他的文件當(dāng)中可見,不能被其他文件所用。

  定義靜態(tài)函數(shù)的好處:

  <1>其他文件中可以定義相同名字的函數(shù),不會發(fā)生沖突

  這里我一直強調(diào)數(shù)據(jù)和函數(shù)的本地化,這對于程序的結(jié)構(gòu)甚至優(yōu)化都有巨大的好處,更大的作用是,本地化的數(shù)據(jù)和函數(shù)能給人傳遞很多有用的信息,能約束數(shù)據(jù)和函數(shù)的作用范圍。在C++的對象和類中非常注重的私有和公共數(shù)據(jù)/函數(shù)其實就是本地和全局?jǐn)?shù)據(jù)/函數(shù)的擴展,這也從側(cè)面反應(yīng)了本地化數(shù)據(jù)/函數(shù)的優(yōu)勢。

  最后說一下存儲說明符,在標(biāo)準(zhǔn)C語言中,存儲說明符有以下幾類:

  auto、register、extern和static

  對應(yīng)兩種存儲期:自動存儲期和靜態(tài)存儲期。

  auto和register對應(yīng)自動存儲期。具有自動存儲期的變量在進(jìn)入聲明該變量的程序塊時被建立,它在該程序塊活動時存在,退出該程序塊時撤銷。

  關(guān)鍵字extern和static用來說明具有靜態(tài)存儲期的變量和函數(shù)。用static聲明的局部變量具有靜態(tài)存儲持續(xù)期(static storage duration),或靜態(tài)范圍(static extent)。雖然他的值在函數(shù)調(diào)用之間保持有效,但是其名字的可視性仍限制在其局部域內(nèi)。靜態(tài)局部對象在程序執(zhí)行到該對象的聲明處時被首次初始化。

  2. const 關(guān)鍵字

  const關(guān)鍵字也是一個優(yōu)秀程序中經(jīng)常用到的關(guān)鍵字。關(guān)鍵字const 的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實際上,聲明一個參數(shù)為常量是為了告訴了用戶這個參數(shù)的應(yīng)用目的。通過給優(yōu)化器一些附加的信息,使用關(guān)鍵字const 也許能產(chǎn)生更緊湊的代碼。合理地使用關(guān)鍵字const 可以使編譯器很自然地保護那些不希望被改變的參數(shù),防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現(xiàn)。

  深入理解const關(guān)鍵字,你必須知道:

  a. const關(guān)鍵字修飾的變量可以認(rèn)為有只讀屬性,但它絕不與常量劃等號。

  如下代碼:

  const int i=5;

  int j=0;

  ...

  i=j; //非法,導(dǎo)致編譯錯誤,因為只能被讀

  j=i; //合法

  b. const關(guān)鍵字修飾的變量在聲明時必須進(jìn)行初始化。如下代碼:

  const int i=5; //合法

  const int j; //非法,導(dǎo)致編譯錯誤

  c. 用const聲明的變量雖然增加了分配空間,但是可以保證類型安全。const最初是從C++變化得來的,它可以替代define來定義常量。在舊版本(標(biāo)準(zhǔn)前)的c中,如果想建立一個常量,必須使用預(yù)處理器:

  #define PI 3.14159

  此后無論在何處使用PI,都會被預(yù)處理器以3.14159替代。編譯器不對PI進(jìn)行類型檢查,也就是說可以不受限制的建立宏并用它來替代值,如果使用不慎,很可能由預(yù)處理引入錯誤,這些錯誤往往很難發(fā)現(xiàn)。而且,我們也不能得到PI的地址(即不能向PI傳遞指針和引用)。const的出現(xiàn),比較好的.解決了上述問題。

  d. C標(biāo)準(zhǔn)中,const定義的常量是全局的。

  e. 必須明白下面語句的含義,我自己是反復(fù)記憶了許久才記住,方法是:若是想定義一個只讀屬性的指針,那么關(guān)鍵字const要放到‘* ’后面。

  char *const cp; //指針不可改變,但指向的內(nèi)容可以改變

  char const *pc1; //指針可以改變,但指向的內(nèi)容不能改變

  const char *pc2; //同上(后兩個聲明是等同的)

  f. 將函數(shù)傳入?yún)?shù)聲明為const,以指明使用這種參數(shù)僅僅是為了效率的原因,而不是想讓調(diào)用函數(shù)能夠修改對象的值。

  參數(shù)const通常用于參數(shù)為指針或引用的情況,且只能修飾輸入?yún)?shù);若輸入?yún)?shù)采用“值傳遞”方式,由于函數(shù)將自動產(chǎn)生臨時變量用于復(fù)制該參數(shù),該參數(shù)本就不需要保護,所以不用const修飾。例子:

  void fun0(const int * a );

  void fun1(const int & a);

  調(diào)用函數(shù)的時候,用相應(yīng)的變量初始化const常量,則在函數(shù)體中,按照const所修飾的部分進(jìn)行常量化,如形參為const int * a,則不能對傳遞進(jìn)來的指針?biāo)赶虻膬?nèi)容進(jìn)行改變,保護了原指針?biāo)赶虻膬?nèi)容;如形參為const int & a,則不能對傳遞進(jìn)來的引用對象進(jìn)行改變,保護了原對象的屬性。

  g. 修飾函數(shù)返回值,可以阻止用戶修改返回值。(在嵌入式C中一般不用,主要用于C++)

  h. const消除了預(yù)處理器的值替代的不良影響,并且提供了良好的類型檢查形式和安全性,在可能的地方盡可能的使用const對我們的編程有很大的幫助,前提是:你對const有了足夠的理解。

  最后,舉兩個常用的標(biāo)準(zhǔn)C庫函數(shù)聲明,它們都是使用const的典范。

  1.字符串拷貝函數(shù):char *strcpy(char *strDest,const char *strSrc);

  2.返回字符串長度函數(shù):int strlen(const char *str);

  3. volatile關(guān)鍵字

  一個定義為volatile 的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。

  由于訪問寄存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優(yōu)化。比如:

  static int i=0;

  int main(void)

  {

  ...

  while (1)

  {

  if (i)

  dosomething();

  }

  }

  /* Interrupt service routine. */

  void ISR_2(void)

  {

  i=1;

  }

  程序的本意是希望ISR_2中斷產(chǎn)生時,在main當(dāng)中調(diào)用dosomething函數(shù),但是,由于編譯器判斷在main函數(shù)里面沒有修改過i,因此可能只執(zhí)行一次對從i到某寄存器的讀操作,然后每次if判斷都只使用這個寄存器里面的“i副本”,導(dǎo)致dosomething永遠(yuǎn)也不會被調(diào)用。

  如果將將變量加上volatile修飾,則編譯器保證對此變量的讀寫操作都不會被優(yōu)化(肯定執(zhí)行)。此例中i也應(yīng)該如此說明。

  一般說來,volatile用在如下的幾個地方:

  1、中斷服務(wù)程序中修改的供其它程序檢測的變量需要加volatile;

  2、多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile;

  3、存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能有不同意義;

  不懂得volatile 的'內(nèi)容將會帶來災(zāi)難,這也是區(qū)分C語言和嵌入式C語言程序員的一個關(guān)鍵因素。為強調(diào)volatile的重要性,再次舉例分析:

  代碼一:

  int a,b,c;

  //讀取I/O空間0x100端口的內(nèi)容

  a= inword(0x100);

  b=a;

  a=inword(0x100)

  c=a;

  代碼二:

  volatile int a;

  int a,b,c;

  //讀取I/O空間0x100端口的內(nèi)容

  a= inword(0x100);

  b=a;

  a=inword(0x100)

  c=a;

  在上述例子中,代碼一會被絕大多數(shù)編譯器優(yōu)化為如下代碼:

  a=inword(0x100)

  b=a;

  c=a;

  這顯然與編寫者的目的不相符,會出現(xiàn)I/O空間0x100端口漏讀現(xiàn)象,若是增加volatile,像代碼二所示的那樣,優(yōu)化器將不會優(yōu)化掉任何代碼.

  從上面來看,volatile關(guān)鍵字是會降低編譯器優(yōu)化力度的,但它保證了程序的正確性,所以在適合的地方使用關(guān)鍵字volatile是件考驗編程功底的事情.

  4.struct與typedef關(guān)鍵字

  面對一個人的大型C/C++程序時,只看其對struct的使用情況我們就可以對其編寫者的編程經(jīng)驗進(jìn)行評估。因為一個大型的C/C++程序,勢必要涉及一些(甚至大量)進(jìn)行數(shù)據(jù)組合的結(jié)構(gòu)體,這些結(jié)構(gòu)體可以將原本意義屬于一個整體的數(shù)據(jù)組合在一起。從某種程度上來說,會不會用struct,怎樣用struct是區(qū)別一個開發(fā)人員是否具備豐富開發(fā)經(jīng)歷的標(biāo)志。

  在網(wǎng)絡(luò)協(xié)議、通信控制、嵌入式系統(tǒng)的`C/C++編程中,我們經(jīng)常要傳送的不是簡單的字節(jié)流(char型數(shù)組),而是多種數(shù)據(jù)組合起來的一個整體,其表現(xiàn)形式是一個結(jié)構(gòu)體。

  經(jīng)驗不足的開發(fā)人員往往將所有需要傳送的內(nèi)容依順序保存在char型數(shù)組中,通過指針偏移的方法傳送網(wǎng)絡(luò)報文等信息。這樣做編程復(fù)雜,易出錯,而且一旦控制方式及通信協(xié)議有所變化,程序就要進(jìn)行非常細(xì)致的修改。

  用法:

  在C中定義一個結(jié)構(gòu)體類型要用typedef:

  typedef struct Student

  {

  int a;

  }Stu;

  于是在聲明變量的時候就可:Stu stu1;

  如果沒有typedef就必須用struct Student stu1;來聲明

  這里的Stu實際上就是struct Student的別名。

  另外這里也可以不寫Student(于是也不能struct Student stu1;了)

  typedef struct

  {

  int a;

  }Stu;

  struct關(guān)鍵字的一個總要作用是它可以實現(xiàn)對數(shù)據(jù)的封裝,有一點點類似與C++的對象,可以將一些分散的特性對象化,這在編寫某些復(fù)雜程序時提供很大的方便性.

  比如編寫一個菜單程序,你要知道本級菜單的菜單索引號、焦點在屏上是第幾項、顯示第一項對應(yīng)的菜單條目索引、菜單文本內(nèi)容、子菜單索引、當(dāng)前菜單執(zhí)行的功能操作。若是對上述條目單獨操作,那么程序的復(fù)雜程度將會大到不可想象,若是菜單層數(shù)少些還容易實現(xiàn),一旦菜單層數(shù)超出四層,呃~我就沒法形容了。若是有編寫過菜單程序的朋友或許理解很深。這時候結(jié)構(gòu)體struct就開始顯現(xiàn)它的威力了:

  //結(jié)構(gòu)體定義

  typedef struct

  {

  unsigned char CurrentPanel;//本級菜單的菜單索引號

  unsigned char ItemStartDisplay; //顯示第一項對應(yīng)的菜單條目索引

  unsigned char FocusLine; //焦點在屏上是第幾項

  }Menu_Statestruct;

  typedef struct

  {

  unsigned char *MenuTxt; //菜單文本內(nèi)容

  unsigned char MenuChildID;//子菜單索引

  void (*CurrentOperate)();//當(dāng)前菜單執(zhí)行的功能操作

  }MenuItemStruct;

  typedef struct

  {

  MenuItemStruct *MenuPanelItem;

  unsigned char MenuItemCount;

  }MenuPanelStruct;

  菜單程序中的結(jié)構(gòu)體定義,這個菜單程序最大可以到256級菜單。當(dāng)初要寫一個菜單程序之前,并沒有對結(jié)構(gòu)體了解多少,也沒有想到使用結(jié)構(gòu)體。只是一層層菜單的單獨處理:如果按鍵按下,判斷是哪個按鍵,調(diào)用對應(yīng)按鍵的子程序,刷屏顯示。這樣處理起來每一層都要判斷當(dāng)前的光標(biāo)所在行,計算是不是在顯示屏的頂層,是不是在顯示層的底層,是不是需要翻頁等等,非常的繁瑣。

【C語言關(guān)鍵字】相關(guān)文章:

C語言學(xué)習(xí)經(jīng)驗07-01

C語言學(xué)習(xí)經(jīng)驗(精品)07-01

c語言中什么是靜態(tài)變量05-26

C語言學(xué)習(xí)經(jīng)驗[精華6篇]07-01

計算機二級C語言難不難 考什么03-05

C位的作文11-21

C羅將缺席季前賽,曼晚稱C羅獲得額外假期03-11

維生素c的故事反思07-15

為什么不看好C2C二手車電商08-14

主站蜘蛛池模板: 梁河县| 津市市| 瑞安市| 临海市| 旌德县| 平乡县| 韶山市| 石门县| 庆安县| 上蔡县| 桂平市| 蓬安县| 阳山县| 米易县| 冕宁县| 仁寿县| 沛县| 牙克石市| 上杭县| 固镇县| 绥中县| 仁怀市| 确山县| 永清县| 天祝| 容城县| 绥宁县| 冀州市| 贵溪市| 东阳市| 改则县| 南阳市| 广平县| 元谋县| 徐汇区| 唐河县| 黑水县| 晋江市| 湟中县| 岢岚县| 内乡县|