激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進程|Fedora|注冊表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE

Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE

2019-10-12 14:00京山游俠 Linux

這篇文章主要介紹了Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE,本文講解了感悟一:C語言標準干不過GNU擴展、感悟二:指針和數(shù)組還真是不一樣、感悟三:、語言中的不完全類型(Incomplete Types)、打造C/C++的IDE等內(nèi)

C語言在Linux系統(tǒng)中的重要性自然是無與倫比、不可替代,所以我寫Linux江湖系列不可能不提C語言。C語言是我的啟蒙語言,感謝C語言帶領(lǐng)我進入了程序世界。雖然現(xiàn)在不靠它吃飯,但是仍免不了經(jīng)常和它打交道,特別是在Linux系統(tǒng)下。

  Linux系統(tǒng)中普遍使用的是GNU-C,這里有一份Gnu-C語言手冊.pdf。The GNU C Reference Manual的主頁在這里:http://www.gnu.org/software/gnu-c-manual/。C語言的內(nèi)核極其緊湊,該手冊總共只有91頁,去掉目錄、附錄和索引后就只有70頁。我一般一個多小時就可以將其從頭至尾復(fù)習(xí)一遍。我曾有過將其翻譯成中文的想法,后來還是放棄了。翻譯這種字斟句酌的事情還是讓別人來干吧。我只寫寫我自己的感悟。

感悟一:C語言標準干不過GNU擴展

   最近為了研究X Window的底層協(xié)議,開始嘗試使用XCB編程。當(dāng)我打開XCB的頭文件的時候,我被大量的__restrict__關(guān)鍵字驚呆了,好在有GNU C語言手冊為我答疑解惑。__restrict__又是一個GNU擴展的關(guān)鍵字,后面我會詳細講解該關(guān)鍵字的用途。其實C語言的C99標準中已經(jīng)引入了restrict關(guān)鍵字,沒有前后的下劃線,但是在大量的開源代碼中,使用最普遍的還是GNU的擴展,而不是C語言標準。

  和restrict關(guān)鍵字有相同命運的還有inline、_Complex等,它們都是在C99標準中引入的關(guān)鍵字,但是其實在C99標準出來之前,GNU C中早就有了__inline__、__complex__等擴展關(guān)鍵字。還記得多年前我學(xué)習(xí)Linux 0.11版的源代碼時,看到大量的__inline__曾經(jīng)疑惑不已,不知道為什么Linus在91年就能用上了如此先進的語言功能,后來才知道,這是GNU的擴展關(guān)鍵字。

  C語言的標準有C89和C99,使用GCC的時候甚至要顯示指定-std=c99才能全面支持C99標準,所以在開源界,大家還是喜歡首選GNU的擴展關(guān)鍵字。比如__inline__、__complex__和__restrict__。總而言之,C語言標準干不過GNU擴展。

  下面來看看__restrict__的真正含義。還記得CSDN上曾經(jīng)載過一篇文章《為什么有些語言會比別的快》,其中提到“很長一段時間,相同的兩個程序在Fortran和C(或者C++)中運行,F(xiàn)ortran會快一些,因為Fortran的優(yōu)化做的更好。這是真的,就算C語言和Fortran的編譯器用了相同的代碼生成器也是一樣。這個不同不是因為Fortran的某種特性,事實上恰恰相反,是因為Fortran不具備的特性。”這是因為C語言中的指針給編譯器的優(yōu)化帶來了困難,文章中繼續(xù)說道:“問題就來了。這些指針可以代替任何內(nèi)存地址。更重要的是,他們可以重疊。輸出數(shù)組的內(nèi)存地址也可以同時是輸入數(shù)組的。甚至可以部分重疊,輸出數(shù)組可以覆蓋一個輸入數(shù)組的一半。這對編譯器優(yōu)化來說是個大問題,因為之前基于數(shù)組的優(yōu)化不再適用。特別的,添加元素的順序也成問題,如果輸出重疊的數(shù)組,計算的結(jié)果會變得不確定,取決于輸出元素的動作是發(fā)生在元素被覆蓋之前還是之后。”

  有了__restrict__,C語言的該問題將不復(fù)存在。用__restrict__修飾一個指針后,①該指針只能在定義的時候被初始化;②不會再有別的指針指向該指針指向的內(nèi)存,因此編譯器可以對算法進行優(yōu)化。如下代碼:
 

復(fù)制代碼

代碼如下:


int * __restrict__ p = (int*)malloc(100*sizeof(int));


指針p有__restrict__關(guān)鍵字修飾,所以它只能在定義的時候被初始化,以后不能賦值,而沒有__restrict__修飾的指針,可以隨時賦值,如下:

復(fù)制代碼

代碼如下:


int arr[100];
int* pArr;
pArr = arr;


指針pArr沒有被__restrict__關(guān)鍵字修飾,所以可以將數(shù)組的首地址賦值給它。

 

比如我們定義一個函數(shù)對兩塊數(shù)據(jù)進行操作,結(jié)果放入第3塊內(nèi)存,如下:
 

復(fù)制代碼

代碼如下:


void func1(void* p1, void* p2, void* p3, int size){
for(int i=0; i<size; i++){
p3[i] = p1[i] + p2[i];
}
}


很顯然,由于編譯器沒辦法判斷指針p1、p2、p3指向的內(nèi)存是否重疊,所以無法進行優(yōu)化,加上__restrict__關(guān)鍵字后,如下:

復(fù)制代碼

代碼如下:


void func1(void* __restrict__ p1, void* __restrict__ p2, void* __restrict__ p3, int size){
for(int i=0; i<size; i++){
p3[i] = p1[i] + p2[i];
}
}

 

相當(dāng)于明確告訴編譯器這幾塊內(nèi)存不會重疊,所以編譯器就可以放心大膽對程序進行優(yōu)化。

   另一個關(guān)鍵字是_Complex,C99才引入,而且需要包含<complex.h>頭文件。其實在GNU C中,早就有__complex__、__real__、__imag__等擴展關(guān)鍵字。如下代碼:
 

復(fù)制代碼

代碼如下:


#include <stdlib.h>
#include <stdio.h></p> <p>int main(){
__complex__ a = 3 + 4i;
__complex__ b = 5 + 6i;
__complex__ c = a + b;
__complex__ d = a * b;
__complex__ e = a / b;
printf("a + b = %f + %fi\n", __real__ c, __imag__ c);
printf("a * b = %f + %fi\n", __real__ d, __imag__ d);
printf("a / b = %f + %fi\n", __real__ e, __imag__ e);
return 0;
}

 

  可以看到,在C語言中也可以直接對復(fù)數(shù)進行計算。數(shù)值計算再也不是Fortran的專利。

 感悟二:指針和數(shù)組還真是不一樣

  從學(xué)C語言開始,老師就教導(dǎo)我們說指針和數(shù)組是一樣的,它們可以用同樣的方式進行操作。而事實上,指針和數(shù)組還是有差別的。直到多年后讀《C專家編程》,才直到所謂指針和數(shù)組一樣是一個美麗的錯誤,只是因為在《The C Programming Language》這本書里,把“作為函數(shù)參數(shù)時,指針和數(shù)組一樣”這樣一句話前后分開分別印到了兩頁而已。

  比如,指針不保存數(shù)據(jù)的長度信息,而數(shù)組有,如下代碼:
 

復(fù)制代碼

代碼如下:


#include <stdlib.h>
#include <stdio.h></p> <p>int main(){
int* p = (int*)malloc(100*sizeof(int));
int arr[100] = {0};
printf("The size of p: %d\n", sizeof(p));
printf("The size of arr: %d\n", sizeof(arr));
return 0;
}

 

這段代碼的運行結(jié)果為:
 

復(fù)制代碼

代碼如下:


The size of p: 8
The size of arr: 400


  我們經(jīng)常可以使用如下的代碼片段來獲得一個數(shù)組中有多少個元素,如下:

復(fù)制代碼

代碼如下:


int arr[100];
size_t length = sizeof(arr)/sizeof(int);


  但是,當(dāng)使用數(shù)組作為函數(shù)的參數(shù)的時候,數(shù)組會退化成指針。如下代碼:

復(fù)制代碼

代碼如下:


#include <stdlib.h>
#include <stdio.h></p> <p>void test_array(int arr[]){
printf("The size of arr in function: %d\n", sizeof(arr));
return;
}</p> <p>int main(){
int arr[100] = {0};
printf("The size of arr in main: %d\n", sizeof(arr));
test_array(arr);
return 0;
}

 

這段代碼的運行結(jié)果為:
 

復(fù)制代碼

代碼如下:


The size of arr in main: 400
The size of arr in function: 8

 

感悟三:C語言中的不完全類型(Incomplete Types)

   在GNU C中可以定義不完全類型,不完全類型主要有兩種,一種是空的結(jié)構(gòu),一種是空的數(shù)組,比如:
 

復(fù)制代碼

代碼如下:


struct point;
char name[0];


空的結(jié)構(gòu)不能定義變量,只能使用空結(jié)構(gòu)的指針。空結(jié)構(gòu)可以在后面再將它補充完整,如下:

復(fù)制代碼

代碼如下:


struct point{
int x,y;
};


空結(jié)構(gòu)在定義鏈表的時候經(jīng)常用到,如下:

復(fù)制代碼

代碼如下:


struct linked_list{
struct linked_list* next;
int x;
/*other elements here perhaps */
}
struct linked_list* head;

 

  還有一種不完全類型就是將一個結(jié)構(gòu)的最后一項定義為一個空的數(shù)組,這樣可以用來表示一個可變長度的結(jié)構(gòu)或數(shù)組,演示該技術(shù)的代碼如下:

 

復(fù)制代碼

代碼如下:


#include <stdlib.h>
#include <stdio.h></p> <p>typedef struct {
int length;
int arr[0];
} incomplete_type;</p> <p>int main(){
char hello[] = "Hello, world!";
int length = sizeof(hello) / sizeof(char);
incomplete_type* p = (incomplete_type*)malloc(sizeof(int) + length*sizeof(char));
p->length = length;
for(int i=0; i<p->length; i++){
p->arr[i] = hello[i];
}
printf("p->length=%d\n", p->length);
printf("p->arr=%s\n", p->arr);
}

 

打造C/C++的IDE

  后面的內(nèi)容展示如何將Vim打造成一個半自動的C/C++ IDE。讀過我的Java博客的朋友應(yīng)該知道,其實我更喜歡用Eclipse。只有在需要寫非常簡單的程序(比如做習(xí)題)的情況下,我才會用Vim。這在我的《打造屬于自己的Vim》中有論述。在這篇文章中我展示了怎么使用Vundle管理插件以及怎么怎么閱讀幫助文檔,同時展示了taglist.vim的簡單用法。如果要用Vim來寫C/C++程序,還需要做少許擴展。

  第一,安裝以下幾個插件,由于使用Vundle管理插件,所以只需要把插件名寫入.vimrc配置文件,然后運行:BundleInstall即可,如下圖:

Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE分別介紹一下這幾個插件。The-NERD-tree是一個瀏覽目錄和文件的插件,可以使用:help NERD_tree.txt查看它的幫助文檔。taglist.vim是瀏覽符號以及在符號之間跳轉(zhuǎn)的插件,使用:help taglist.txt查看它的幫助文檔。a.vim是在源代碼文件和頭文件之間跳轉(zhuǎn)的插件,不需要幫助文檔,它的命令就是:A。c.vim是提供IDE功能的主要插件,它提供的功能有自動注釋、反注釋、自動插入代碼塊及自動運行,如果安裝了splint,還可以對代碼進行靜態(tài)檢查,使用:help csupport.txt查看它的文檔。OmniCppComplete是一個提供自動補全功能的插件,使用:help omnicppcomplete.txt查看它的文檔。

  這些插件中,taglist.vim和OmniCppComplete需要ctags軟件的支持,所以需要安裝exuberant-ctags軟件包,在Fedora 20中,只需要使用yum install ctags即可自動安裝。

  第二,生成tags數(shù)據(jù)庫,并將其加入到Vim中。

  我們寫C程序的時候,使用到的文件主要存在于兩個地方,一個是我們工作的當(dāng)前目錄,另外一個是/usr/include。所以要到/usr/include目錄下使用ctags命令生成tags數(shù)據(jù)庫文件。為了使tags數(shù)據(jù)庫中包含盡可能多的信息(結(jié)構(gòu)、枚舉、類、函數(shù)、宏定義等等),需要指定ctags的參數(shù),如下:

Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE

 然后將該tags文件的路徑加入到.vimrc配置文件中,同時設(shè)置一個鍵盤映射,使得按Ctrl+F12時,在工作目錄中調(diào)用ctags命令。如下配置文件的最后兩行:
Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE

  然后,在使用Vim寫C程序的時候,如果輸入了.、->這樣的元素,則其成員會自動補全。如果輸入的是一個字符串(比如函數(shù)名),可以按Ctrl-X Ctrl-O調(diào)用自動補全,如下圖:

Linux折騰記(六):感悟GNU C及把Vim打造成C/C++的半自動化IDE

不僅會彈出候選窗口,而且在最上面的窗口中會顯示函數(shù)的完整的簽名,及其所在的文件。這對于我們經(jīng)常記不全函數(shù)名、記不清函數(shù)簽名的人來說,已經(jīng)是莫大的福音了。

  taglist.vim和OmniCppComplete插件提供的功能用起來都只需要一個命令,而c.vim提供的命令就比較多了。而且在c.vim的幫助文檔中并沒有列出所有功能的命令,有一個辦法可以學(xué)習(xí)這些命令,那就是打開GVim,通過GVim菜單中的C/C++菜單來學(xué)習(xí)c.vim提供的功能和命令。

  相比網(wǎng)上其它的將Vim打造成IDE的文章,我的配置比較簡單,基本上只安裝了幾個插件,而沒有做過多的設(shè)置。當(dāng)我需要某個功能的時候,我會使用命令顯式地調(diào)用它,所以,稱它為半自動化IDE吧。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: videos高潮| 毛片118极品美女写真 | a视频在线播放 | 97久色| 久久久久久69 | 久久福利小视频 | 老a影视网站在线观看免费 欧美日韩成人一区二区 | 91情侣在线偷精品国产 | 日本中文视频 | 在线免费黄色网 | 欧美日韩国产成人在线观看 | 91看片资源| 理论片中文字幕 | 99麻豆久久久国产精品免费 | 午夜国产小视频 | 人人舔人人插 | 久久久久久久一区二区 | 久久久久久亚洲综合影院红桃 | 午夜爱爱福利 | 欧美日韩一区,二区,三区,久久精品 | 黄色免费小视频网站 | 亚洲码无人客一区二区三区 | 99在线精品视频免费观看20 | 亚洲情av | 欧美高清另类自拍视频在线看 | 成人免费观看av | 黄色网址在线免费 | 国产免费让你躁在线视频 | 免费观看一区二区三区视频 | 午夜视频在线免费播放 | 天天舔天天插 | 国产亚洲精彩视频 | 99www| 成人免费一区二区三区 | 欧洲精品久久久久69精品 | 精品黑人一区二区三区国语馆 | 精品中文字幕在线播放 | 久草最新在线 | 成人黄色短视频在线观看 | 黄色片网站在线看 | 久久久成人免费视频 |