1. 程式人生 > >GNU C 、ANSI C、標準C、標準c++的區別和聯絡

GNU C 、ANSI C、標準C、標準c++的區別和聯絡

ANSI C和標準C++的差別

這裡的ANSI C指的是最新的標準-C99

1、ANSI C不支援引用

2、ANSI C不支援函式過載

3、ANSI C多了兩個整型(long long、unsigned long long),不過最新的C++編譯器已經支援這兩種整型

4、ANSI C不支援C++中的一個變數初始化方式,例如:int a(8);

5、ANSI C宣告結構時必須使用struct關鍵字,而標準C++不需要

6、ANSI C標準庫中的一些標頭檔案,在標準C++中有了新的名稱,例如ctime、cstring、climits、cfloat、cctype,有些檔案不僅是名稱上的變化

7、ANSI C不支援名稱空間

8、ANSI C不包含bool型別,以及true和false關鍵字

9、宣告函式時,引數為空的含義不同。在ANSI C中表示接受任意個數的引數,而在標準C++中表示不接受引數

10、ANSI C不支援行內函數

11、ASNI C不支援預設引數

12、ANSI C不支援可用於全域性變數的作用域解析操作符(::)

13、使用const定義的全域性常量在ANSI C中具有外部連結性,在標準C++中具有內部連結性,所以在標準C++中宣告外部連結性的全域性常量必須使用extern,例如:extern const int a = 10;

GNU C比ANSI C擴充套件的地方

1.允許零長度陣列

GNU C允許零長度陣列,在定義變長物件的頭結構時,這個特性非常有用。

[cpp] view plaincopyprint?
  1. struct var_data  
  2. {  
  3.       int len;  
  4.       char data[0];  
  5. };  

char data[0]僅僅意味著程式中通過var_data的結構體例項的data[index]成員可以訪問len之後的第index個地址,並沒有為data[0]分配記憶體。

假設struct var_data的資料域儲存在struct var_data緊接著的記憶體區域,通過如下程式碼可以遍歷這些資料:

[cpp] view plaincopyprint?
  1. struct var_data s;  
  2. ...  
  3. for (i=0;i<s.len;i++)  
  4. {  
  5.     printf("%02x",s.data[i]);  
  6. }  

2、case範圍

GNU C 支援case x...y 這樣的語法,區間[x,y]的數都會滿足這個case的條件,記得資料結構試驗時,有的同學為了做選單使用了近100個case,還好我做的是GUI的

[cpp] view plaincopyprint?
  1. switch(c)  
  2. {  
  3.       case'0'...'9': c-='0';  
  4.       break;  
  5.       case'a'...'f': c-='a'-10;  
  6.       break;  
  7.       case'A'...'F': c-='A'-10;  
  8.       break;  
  9. }  

這個case的特點大家都看得出來,比標準C少敲了多少case啊

3、語句表示式

GNU C把包含在括號裡的複合語句看做是一個表示式,稱為語句表示式,它可以出現在任何允許表示式的地方。我們可以在語句表示式中使用原本只能在複合語句中使用的迴圈變數、區域性變數等,例如

[cpp] view plaincopyprint?
  1. #define min_t(type,x,y) /
  2. ({type __x=(x); type __y=(y);__x<__y?__x:__y})  
  3. int ia,ib,mini;  
  4. mini=min_t(int,ia,ib);  

這樣,因為重新定義了__x和__y這兩個區域性變數,所以上述方法定義的巨集將不會有副作用。在標準C中,對應的巨集通常會有副作用:

#define min(x,y) ((x)<(y)?(x):(y))

而程式碼min(++ia,++ib)將會被展開為

((++ia)<(++ib)?(++ia):(++ib)) 傳入巨集的引數會被增加兩次。

這個在 嵌入式程式設計師應知道的0x10個基本問題 裡有講過。

4、typeof關鍵字

typeof(x)語句可以獲得x的型別,因此,我們可以藉助typeof重新定義第3條提到的min_t這個巨集

[cpp] view plaincopyprint?
  1. #define min(x,y) /
  2. ({ /  
  3.       const typeof(x) _x=(x);/  
  4.       const typeof(y) _y=(y);/  
  5.       (void) (&_x==&_y);/  
  6.        _x<_y ? _x: _y ; })  

我們不需要像第三條時那樣傳一個type進去,因為通過typeof(x)可以得到type。

程式碼 (void) (&_x==&_y);的作用是檢查_x和_y的型別是否一致。

5、可變引數的巨集

標準C只支援可變引數的函式,意味著函式的引數可以是不固定的

例如printf()函式的原型是

int printf(const char *format [,argument]...)

而在GNU C中,巨集也可以接受可變數目的引數,例如

#define pr_debug(fmt,arg...) printk(fmt,##arg)

這裡arg表示其餘的引數可以是零個或多個,這些引數以及引數之間的逗號構成arg的值,

在巨集擴充套件時替換arg ,例如

pr_debug("%s:%d",filename,line);

被擴充套件為

printk("%s:%d",filename,line);

使用##的原因是為了處理arg不代表任何引數的情況,這時候,前面的逗號就變得多餘了。

使用##之後,GNU C前處理器會丟棄前面的逗號,這樣程式碼

pr_debug("success!/n") 會被正確擴充套件為 printk("success!/n")

而不是 printk("success!/n",);

6.標號元素

標準c要求陣列或結構體的初始化值必須以固定的順序出現,在GNU C中,通過指定索引或結構體成員名,允許初始化值得以任意順序出現。

指定陣列索引的方法是在初始化值前新增 [INDEX]= ,當然也可以用 [FIRST...LAST]= 的形式指定一個範圍。例如下面的程式碼定義一個數組,並把其中的所有元素賦值為0:

unsigned char data[MAX] ={[0...MAX-1]=0 };

下面的程式碼藉助結構體成員名初始化結構體:

[cpp] view plaincopyprint?
  1. struct file_operations DEMO_fops = {  
  2.     owner :    THIS_MODULE,  
  3.     llseek:      DEMO_llseek,  
  4.     read:       DEMO_read,  
  5.     write:       DEMO_write,  
  6.     ioctl:        DEMO_ioctl,  
  7.     open:        DEMO_open,  
  8.     release:   DEMO_release,  
  9. };  

但是Linux 2.6還是推薦採用標準C的方式,如下

[cpp] view plaincopyprint?
  1. struct file_operations DEMO_fops = {  
  2.     .owner =    THIS_MODULE,  
  3.     .llseek =   DEMO_llseek,  
  4.     .read =     DEMO_read,  
  5.     .write =    DEMO_write,  
  6.     .ioctl =    DEMO_ioctl,  
  7.     .open =     DEMO_open,  
  8.     .release = DEMO_release,  
  9. };  

7.當前函式名

GUN C預定義了兩個識別符號儲存當前的函式名,__FUNCTION__儲存函式在原始碼中的名字,

__PRETTY_FUNCTION__儲存帶語言特色的名字。在c函式中,這兩個名字是相同的。

void example()

{

      printf("This is function: %s ",__FUNCTION__);

}

程式碼中的__FUNCTION__意味著字串"example"

8、特殊屬性宣告

GNU C允許宣告函式、變數和型別的特殊屬性,以便進行手工的程式碼優化和定製程式碼檢查的方法。指定一個宣告的屬性,只需要在申明後新增 __attribute__((ATTRIBUTE))

其中ATTRIBUTE為屬性說明,如果存在多個屬性,則以逗號分隔。GNU C支援noreturn format section aligned packed等十多個屬性

noreturn屬性作用於函式,表示該函式從不返回。這會讓編譯器優化程式碼,並消除不必要的的警告資訊。例如

#define ATTRIB_NORET __attribute__ ((noreturn)) ....

asmlinkage NORET_TYPE void do_exit(long error_code) ATTRIB_NORET;

format屬性也可用於函式,表示該函式printf scanf 或strftime風格的引數,指定format屬性可以讓編譯器根據格式串檢查引數型別。例如:

asmlinkage int printk(const char * fmt,...)/

__attribute__((format(printf,1,2)));

詳細的可以看http://blog.163.com/sunm_lin/blog/static/9192142200741533038695/

unused屬性作用於函式和變數,表示該函式或變數可能不會被用到,避免編譯器產生的警告資訊。

aligned屬性指定結構體、變數、聯合體的對齊方式。packed屬性作用於變數和型別,表示壓縮結構體,使用最小的記憶體。

[cpp] 

相關推薦

GradleGradle Wrapper與Android Plugin for Gradle的區別聯絡

原文連結:https://www.cnblogs.com/jiangxinnju/p/8229129.html 總結: Gradle:是一個專案構建系統,類似於Maven。Gradle並不是只能用於Android,而是Android引用裡Gradle。https://docs.gradle.

徹底搞懂GradleGradle Wrapper與Android Plugin for Gradle的區別聯絡

歡迎和大家交流技術相關問題: 郵箱: [email protected] 部落格園地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://github.com/jiangxincode 知乎地址: https://www.zhihu.com/

GNU C ANSI C標準C標準c++的區別聯絡

ANSI C和標準C++的差別 這裡的ANSI C指的是最新的標準-C99 1、ANSI C不支援引用 2、ANSI C不支援函式過載 3、ANSI C多了兩個整型(long long、unsigned long long),不過最新的C++編譯器已經支援這兩種整型 4、ANSI C不支援C+

C#中結構體區別聯絡

結構體 結構體定義 結構體是一種值型別,通常用來封裝小型相關變數組。例如座標或者商品的特徵。 結構體是一種自定義的資料型別,相當於一個複合容器,可以儲存多種型別。 結構體由結構體成員構成,結構體成員包含欄位,屬性與方法 結構體建

CC++的區別聯絡(擴充套件知識)

2017/3/17 複習整理:C/C++區別與聯絡; 關於C和C++的區別是面試中經常會被問到的問題,本著即將面試的心態,進行知識整理,並對小知識點進行擴充套件; C/C++的聯絡: C++是C的超集,相容大部分C的語法的結構; 聯絡嘛我只能想

C語言】指標陣列的區別聯絡

1.指標    int  *  p     ( 這裡定義一個指標      p為指標變數     指向的是某一個地址)                2.陣列      int  arr [10]         這裡定義了10個int 型別的資料  可以通過arr[0] 

CC++的區別聯絡

關於C和C++的區別是面試中經常會被問到的問題,本著即將面試的心態,進行知識整理,並對小知識點進行擴充套件; C/C++的聯絡: C++是C的超集,相容大部分C的語法的結構;  聯絡嘛我只能想到這個,畢竟cplusplus嘛! C/C++區別: 第一點

CC++,VC++,MFC之間有什麼區別聯絡

C語言是一種古老而又經久不衰的計算機程式設計語言,大約誕生於上個世紀60年代。由於它的設計有很多優點,多年以來深受廣大程式設計人員的喜愛,並逐漸淘汰了很多其它程式設計語言。我們平時使用的大多數軟體都是用C語言開發的。很多後來出現的一些語言也沿用了很多它的東西。C語言的程式

c++之引用指標的區別聯絡

區別: 1 引用不能為空(必須初始化),指標可為空。 int &a; // error int *a; // ok 2 引用關係一旦被建立,則不能被解除,而指標可以指向別人。 int x = 1, y = 2; int &a = x; a = y;

【小家java】POP(面向過程程式設計)OOP(面向物件程式設計)AOP(面向切面程式設計)三種程式設計思想的區別聯絡

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

【小家java】SessionCookie的區別聯絡分散式session的幾種實現方式

相關閱讀 【小家java】java5新特性(簡述十大新特性) 重要一躍 【小家java】java6新特性(簡述十大新特性) 雞肋升級 【小家java】java7新特性(簡述八大新特性) 不溫不火 【小家java】java8新特性(簡述十大新特性) 飽受讚譽 【小家java】java9

ThreadRunnable的區別聯絡多次start一個執行緒會怎麼樣

一、Java有兩種方式實現多執行緒,第一個是繼承Thread類,第二個是實現Runnable介面。他們之間的聯絡:     1、Thread類實現了Runable介面。   2、都需要重寫裡面Run方法。 二、實現Runnable介面相對於繼承Thread類來說,有如下顯著的好處:

全/半虛擬化硬體/軟體輔助的全虛擬化之間的區別聯絡

全虛擬化 不需要對GuestOS作業系統軟體的原始碼做任何的修改,就可以執行在這樣的VMM中 在全虛擬化的虛擬平臺中,GuestOS並不知道自己是一臺虛擬機器,它會認為自己就是執行在計算機物理硬體裝置上的HostOS。因為全虛擬化的VMM會將一個OS所能夠操作的CPU、記憶體、外設等物理

ubuntu中環境變數檔案/etc/profile.profile.bashrc/etc/bash.bashrc之間的區別聯絡(轉)

寫在前面:不同的發行版裡面檔案的命名可能有所不同,如有的發行版etc目錄下有bashrc,有的發行版下面是bash.bashrc。這個根據每個人不同的發行版注意下具體的檔名稱。 /etc/profile:此檔案為系統的每個使用者設定環境資訊,當用戶第一次登入時,該檔案被執行.並從/etc/pro

Web Service平臺有三種元素構成:SOAPWSDLUDDI。區別聯絡

Web Service平臺有三種元素構成:SOAP、WSDL、UDDI。一個消費者可以在UDDI登錄檔查詢服務,取得服務的WSDL描述,然後通過SOAP來呼叫服務。SOAP、WSDL、UDDI的區別如下:1. SOAP(Simple Object Access Protocol,簡單物件訪問協議)① SOAP

echo語句print語句print_r有啥區別聯絡

echo語句、print語句、print_r有啥區別和聯絡? **echo是PHP語句, print和print_r是函式,語句沒有返回值,函式可以有返回值(即便沒有用) print() 只能打印出簡單型別變數的值(如int,string)** 例子 <?php $a=

人工智慧機器學習深度學習的區別聯絡

機器學習是一種實現人工智慧的方法,深度學習是一種實現機器學習的技術。 人工智慧 在1956年被提出,2012年之前一直飽受爭議,直到機器學習新演算法(深度學習)的出現,人工智慧迎來了大爆發。 人工智慧研究的分支有很多,包含:專家系統、機器學習、進化計算、模糊邏輯、計算機視覺、自然語言處理

KEILuVisionMDK區別聯絡

--------------------------------------------- -- 時間:2018-11-26 -- 建立人:Ruo_Xiao -- 郵箱:[email protected] ----------------------------------------

淺談程序執行緒協程三者之間的區別聯絡

一、程序、執行緒、協程 1,程序 經典定義:一個執行中程式的例項。系統中的每個程式都執行在某個程序的上下文中。(-摘自 CSAPP) 程序是系統資源分配的最小單位   2,執行緒(thread) 執行緒就是執行在程序上下文中的邏輯流。 執行緒是作業系統能夠進行運算排程的最小單位。 &

人工智慧機器學習深度學習之間的區別聯絡

人工智慧: 人工智慧的研究領域細分圖: 目前的科研工作都集中在弱人工智慧這部分,並很有希望在近期取得重大突破,電影裡的人工智慧多半都是在描繪強人工智慧,而這部分在目前的現實世界裡難以真正實現(通常將人工智慧分為弱人工智慧和強人工智慧,前者讓機器具備觀察和感知的能力,可