国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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

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

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

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

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

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

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

感悟一:C語(yǔ)言標(biāo)準(zhǔn)干不過(guò)GNU擴(kuò)展

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

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

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

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

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

復(fù)制代碼

代碼如下:


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


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

復(fù)制代碼

代碼如下:


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


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

 

比如我們定義一個(gè)函數(shù)對(duì)兩塊數(shù)據(jù)進(jìn)行操作,結(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];
}
}


很顯然,由于編譯器沒(méi)辦法判斷指針p1、p2、p3指向的內(nèi)存是否重疊,所以無(wú)法進(jìn)行優(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)存不會(huì)重疊,所以編譯器就可以放心大膽對(duì)程序進(jìn)行優(yōu)化。

   另一個(gè)關(guān)鍵字是_Complex,C99才引入,而且需要包含<complex.h>頭文件。其實(shí)在GNU C中,早就有__complex__、__real__、__imag__等擴(kuò)展關(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語(yǔ)言中也可以直接對(duì)復(fù)數(shù)進(jìn)行計(jì)算。數(shù)值計(jì)算再也不是Fortran的專(zhuān)利。

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

  從學(xué)C語(yǔ)言開(kāi)始,老師就教導(dǎo)我們說(shuō)指針和數(shù)組是一樣的,它們可以用同樣的方式進(jìn)行操作。而事實(shí)上,指針和數(shù)組還是有差別的。直到多年后讀《C專(zhuān)家編程》,才直到所謂指針和數(shù)組一樣是一個(gè)美麗的錯(cuò)誤,只是因?yàn)樵凇禩he C Programming Language》這本書(shū)里,把“作為函數(shù)參數(shù)時(shí),指針和數(shù)組一樣”這樣一句話(huà)前后分開(kāi)分別印到了兩頁(yè)而已。

  比如,指針不保存數(shù)據(jù)的長(zhǎng)度信息,而數(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;
}

 

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

復(fù)制代碼

代碼如下:


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


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

復(fù)制代碼

代碼如下:


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


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

復(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;
}

 

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

復(fù)制代碼

代碼如下:


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

 

感悟三:C語(yǔ)言中的不完全類(lèi)型(Incomplete Types)

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

復(fù)制代碼

代碼如下:


struct point;
char name[0];


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

復(fù)制代碼

代碼如下:


struct point{
int x,y;
};


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

復(fù)制代碼

代碼如下:


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

 

  還有一種不完全類(lèi)型就是將一個(gè)結(jié)構(gòu)的最后一項(xiàng)定義為一個(gè)空的數(shù)組,這樣可以用來(lái)表示一個(gè)可變長(zhǎng)度的結(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打造成一個(gè)半自動(dòng)的C/C++ IDE。讀過(guò)我的Java博客的朋友應(yīng)該知道,其實(shí)我更喜歡用Eclipse。只有在需要寫(xiě)非常簡(jiǎn)單的程序(比如做習(xí)題)的情況下,我才會(huì)用Vim。這在我的《打造屬于自己的Vim》中有論述。在這篇文章中我展示了怎么使用Vundle管理插件以及怎么怎么閱讀幫助文檔,同時(shí)展示了taglist.vim的簡(jiǎn)單用法。如果要用Vim來(lái)寫(xiě)C/C++程序,還需要做少許擴(kuò)展。

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

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

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

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

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

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

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

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

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

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

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

  相比網(wǎng)上其它的將Vim打造成IDE的文章,我的配置比較簡(jiǎn)單,基本上只安裝了幾個(gè)插件,而沒(méi)有做過(guò)多的設(shè)置。當(dāng)我需要某個(gè)功能的時(shí)候,我會(huì)使用命令顯式地調(diào)用它,所以,稱(chēng)它為半自動(dòng)化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 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 免费看一区二区三区 | 日韩免费视频一区二区 | 亚洲精品一区二区 | 亚洲激情视频 | 人人99| 福利资源在线观看 | 国产美女视频自拍 | 狠狠操网站 | 手机黄网www8xcn | 国产一级毛片一级 | 久久久久亚洲精品 | 欧美在线网站 | 午夜资源 | 亚洲午夜av久久乱码 | 久久久国产精品入口麻豆 | 精品中文字幕一区二区三区av | 日本中文在线视频 | 97久久精品人人澡人人爽 | 亚洲成人三区 | 欧美在线小视频 | 国产亚洲人成网站在线观看 | 久久久久无码国产精品一区 | 羞羞视频在线免费观看 | 色花av | 日韩精品一区二区三区精品av | av片免费 | 韩国精品一区 | 亚洲午夜视频 | 亚洲视频在线播放 | 成年人在线看片 | 一级黄色片在线 | 亚洲精品乱码久久久久久蜜桃麻豆 | 色综合久久88色综合天天 | 激情片网站| 久操成人 | 日韩h视频 | 久久中文字幕一区 | 成人免费xxxxx在线视频软件 | 日韩无在线| 国产成人高清精品免费5388 | 欧美午夜精品久久久 |