13 重憶C 之 工程開發命令

pwd
返回了根目錄

這時候看到系統返回了一個 /,這個 / 被我們稱為系統的 根目錄(root),這個位置也就是我們現在在系統中的位置。

但是,我們要開展工作的位置的路徑為:

/home/user/project

所以,我們要學會如何切換我們所在的位置:

輸入 cd 命令,并在 cd 命令后加上空格,在此后輸入開展工作的位置的路徑:

cd /home/user/project

這就是一個層級化路徑,其實其可以通過

cd home
cd user
cd project

逐次到達。

下載輸入 ls -l。
這里就有個old目錄。

image.png
mv main.c old             //mv [選項] 源文件或目錄 目標文件或目錄

再使用移動操作:

移動文件

再創建新文件,通過命令

touch main.c 

創建新文件
這時候可以看見:

創建文件

old目錄下把key刪除

刪除```key```文件

更多相關命令的可附加參數及使用意義,可以通過 man [空格] [命令名]的方式進行進行進一步的查詢(查詢后退出只需敲擊鍵盤上的 q 即可)。

更多復雜的命令,點擊這里

多模塊程序

之前的課中,所有文件操作都是單文件進行。對于一個只完成一個特定的任務,只包含十幾個函數的程序來說,單文件的組織方式還算可以接受,但是當程序越來越長,程序實現的功能越來越多,將他們全部都組織在一個文件里就會變得不那么容易讓人接受了。

因此,我們需要學習如何在 C 語言中將不同功能在多個代碼文件中分別實現,然后將它們看作多個模塊組織在一起為同一個程序服務。


關于gcc命令

原地址:gcc命令中參數c和o混合使用的詳解、弄清gcc test.c 與 gcc -c test.c 的差別

gcc命令使用GNU推出的基于C/C++的編譯器,是開放源代碼領域應用最廣泛的編譯器,具有功能強大,編譯代碼支持性能優化等特點。現在很多程序員都應用GCC,怎樣才能更好的應用GCC。目前,GCC可以用來編譯C/C++、FORTRAN、JAVA、OBJC、ADA等語言的程序,可根據需要選擇安裝支持的語言。

語法

gcc(選項)(參數)

選項

-o:指定生成的輸出文件;
-E:僅執行編譯預處理;
-S:將C代碼轉換為匯編代碼;
-wall:顯示警告信息;
-c:僅執行編譯操作,不進行連接操作。

參數

C源文件:指定C語言源代碼文件。

實例
常用編譯命令選項

假設源程序文件名為test.c

無選項編譯鏈接

gcc test.c

test.c預處理、匯編、編譯并鏈接形成可執行文件。
這里未指定輸出文件,默認輸出為a.out

選項 -o

gcc test.c -o test

test.c預處理、匯編、編譯并鏈接形成可執行文件test
-o選項用來指定輸出文件的文件名。

選項 -E

gcc -E test.c -o test.i

將test.c預處理輸出test.i文件。

選項 -S

gcc -S test.i

將預處理輸出文件test.i匯編成test.s文件。
選項 -c

gcc -c test.s

將匯編輸出文件test.s編譯輸出test.o文件。

無選項鏈接

gcc test.o -o test

將編譯輸出文件test.o鏈接成最終可執行文件test。

選項 -O

gcc -O1 test.c -o test

使用編譯優化級別1編譯程序。級別為1~3,級別越大優化效果越好,但編譯時間越長。

多源文件的編譯方法

如果有多個源文件,基本上有兩種編譯方法:

假設有兩個源文件為test.ctestfun.c

  • 多個文件一起編譯

gcc testfun.c test.c -o test

testfun.ctest.c分別編譯后鏈接成test可執行文件。

  • 分別編譯各個源文件,之后對編譯后輸出的目標文件鏈接。

gcc -c testfun.c

將testfun.c編譯成testfun.o

gcc -c test.c

將test.c編譯成test.o

gcc -o testfun.o test.o -o test

將testfun.o和test.o鏈接成test

以上兩種方法相比較,第一中方法編譯時需要所有文件重新編譯,而第二種方法可以只重新編譯修改的文件,未修改的文件不用重新編譯。


再來復習一下:

gcc -c a.c 編譯成目標文件a.o

gcc -o a a.o 生成執行文件a.exe

gcc a.c 生成執行文件a.exe

gcc -o a -c a.c 編譯成目標文件a

gcc -o a a.c 生成執行文件a.exe

在a.c中引用test.c中的一個函數后:

gcc -c test.c 編譯成目標文件test.o

gcc -c a.c 編譯成目標文件a.o

gcc -o a test.o a.o 生成執行文件a.exe

gcc -o a test.o a.c 生成執行文件a.exe

gcc -o a test.c a.c 生成執行文件a.exe

gcc -o a test.o a.c 生成執行文件a.exe

總結:只要參數中有-c,總是生成目標文件;只要參數中無-c而只有-o,則總是生成執行文件。


在剛開始學習 C 語言的時候,我們曾經學習過,當我們的程序只有一個main.c文件時,我們可以在命令行中通過

gcc -o program main.c

對單個代碼文件進行編譯,生成可執行文件program,并且通過./program運行編譯生成的程序。在我們之前的課程中,計蒜客的學習系統也幫你進行了這樣的操作。

相比于單個文件、單一功能的程序,當程序有多個模塊時,問題就開始變得復雜了。我們對每一個模塊會首先編譯出每個模塊對應的*.o目標代碼文件(relocatable object file),例如:

gcc -c -o set.o set.c

會將我們的一個set.c文件編譯成一個set.o的目標代碼文件。請注意,這里的-c表示生成目標代碼文件。-o與之前單文件的時候一樣,在它之后我們會寫明被生成的文件的名稱。

當我們完成了每一個獨立模塊的編譯并獲得它們的目標代碼文件后,我們可以將我們的主程序的目標代碼文件與他們鏈接在一起。例如:

gcc -o program main.o set.o others.o

將目標代碼文件set.oothers.omain.o在鏈接在一起,并且輸出了 可執行文件(excutable file)program。

我們依然可以通過./program運行編譯生成的程序。

當我們將一個程序寫在多個文件中時,每一個文件中的變量和函數默認都是只有文件內的部分才可以訪問的。但是有一些特殊的全局變量、類型定義、函數可能會需要在多個文件中被使用。

這時候,我們可以將這類的內容單獨寫成一個 頭文件(header file),并且將全局變量、類型定義、函數聲明寫到頭文件中。

對于一個文件set.c,習慣上它的頭文件會被命名為set.h。在所有需要用set.h中全局變量、類型定義、聲明的函數的文件中,用

#include "set.h"

將對應的頭文件引入。在這里的引入頭文件方式和引入系統庫頭文件的方式很類似,只不過這里用的是引號""而不是尖括號<>

由于頭文件里也可以引入頭文件,因此我們可能事實上多次引入同一個文件,比如我們引1.h2.h,且1.h也引入2.h,這時因為2.h被引入了兩次,就有可能出現重復的聲明。為了解決這個問題,我們2.h中定義一個宏,在2.h的最開始判斷這個宏是否被定義過,如果被定義過,就跳過2.h整個文件的內容。

這里我們將會用到兩個新的預處理指令#ifndef xxx#endif,它們成對出現且#ifndef在前,作用是如果這時并未已定義xxx宏,則這對#ifndef xxx, #endif之間的內容有效。(其中xxx可以替換為任意宏名)

這樣```2.h```可以寫為類似于如下的內容:
#ifndef xxx
#define xxx
typedef enum Status { Success, Fail };
typedef struct {
    char *name;
    int age;
} People;
Status go_to_Jisuanke(People);
#endif

細心的同學已經發現,如果在程序中尚未引入2.h的位置定義了xxx宏,則#include "2.h"中的聲明并不會被引入,因此我們不應該在此使用xxx這種平凡的名字。實際上,我們一般會采用一個與頭文件名相關的名字來代替xxx,比如一個常用的代碼風格里,這個宏的名字形式為工程名_路徑名_文件名_H_

總結的幾點

  • 某一代碼中定義的函數如果需要被其他代碼文件所使用,應該將函數的聲明放入頭文件,并在其他代碼文件中引入這一頭文件。
  • 并不需要把每個函數單獨寫成一個模塊,還是應該根據功能的劃分和實現去決定怎么抽出模塊。
  • 可以只有多個.c的文件,也并不一定非要都拆出.h文件。
  • #include可以被用于引入系統庫頭文件也可以被用于引入自己實現的頭文件。
  • 只不過在引入系統庫頭文件時,我們往往會使用尖括號<>,而在引入自己實現的頭文件時一般用引號""
  • gcc時,-o之后寫的是生成可執行文件的名稱。-c的參數的使用會幫我們得到一個對象文件。
//-c和-o都是gcc編譯器的可選參數

//-c表示只編譯(compile)源文件但不鏈接,會把.c或.cc的c源程序編譯成目標文件,一般是.o文件。
//-o用于指定輸出(out)文件名。不用-o的話,一般會在當前文件夾下生成默認的a.out文件作為可執行程序。

//例如
gcc -c test.c          //將生成test.o的目標文件
gcc -o app test.c           //將生成可執行程序app

gcc -c a.c -o a.o          //表示把源文件a.c編譯成指定文件名a.o的中間目標文件(其實在這里,你把-o a.o省掉,效果是一樣的,因為中間文件默認與源文件同名,只是后綴變化)。

Makefile

在前面學習多模塊程序的時候,我們需要先把每個模塊的代碼都生成為目標代碼文件,然后再將目標代碼文件聯編成一個可執行文件。如果每一次編譯都要輸入這么多命令,是不是很復雜呢?如果每次修改一點點內容就需要重新編譯整個工程,是不是很浪費時間呢?

為了解決所遇到的問題,方便開發,我們使用一個叫做make的命令,它可以讀取Makefile文件,并且根據Makefile中的規則描述把源文件生成為可執行的程序文件。

最基本的Makefile中包含了一系列形式如下的規則。請注意,每一條規則的命令前,必須要有一個制表符\t。

目標: 依賴1 依賴2 ...
    命令

例如,可以寫一條規則:

array.o: array.c array.h
   gcc -c -o array.o array.c

表示生成的文件是目標代碼文件array.o,它依賴于array.carray.h
當我們在命令行中執行make array.o時,根據這一規則,如果array.o不存在或者array.carray.h至少之一比array.o更新,就會執行gcc -c -o array.o array.c

我們把上述代碼保存為Makefile,與array.carray.h放在同一目錄,在那個目錄里執行make array.o就能看到效果。

注意:Makefile里的除當前目錄隱藏文件外的第一個目標會成為運行make不指定目標時的默認目標。

再看:

main: array.o main.o
    gcc -o main array.o main.o

main.o: main.c array.h
    gcc -c -o main.o main.c

array.o: array.c array.h
    gcc -c -o array.o array.c

Makefile有多條規則時,如果我們希望只生成其中一個,我們可以在make命令后加上需要生成的目標的名稱。例如,在這里我們可以執行make main.omake array.omake main。當我們執行make main時,make命令發現array.omain.o不存在,就會根據以它們為目標的規則先生成它們。

很多時候,會需要將.o為后綴的目標代碼文件和可執行的程序文件刪除,完全從頭進行編譯。那么我們可以寫一條clean規則,例如:

clean:
    rm -f array.o main.o main

rm命令表示刪除文件,-f表示強制,因此rm -f array.o main.o main

按照預期,當我們執行make clean就可以刪除array.omain.omain了。事實真的這樣嗎?

因為畢竟這時如果已經存在clean文件,rm命令就不會執行了。為了解決這個問題,我們通過一個特殊的方法告訴make這個名為clean的規則在clean存在的時候仍然有效。

.PHONY: clean

clean:
    rm -f array.o main.o main

.PHONY用于聲明一些偽目標,偽目標與普通的目標的主要區別是偽目標不會被檢查是否存在于文件系統中而默認不存在且不會應用默認規則生成它。

在Makefile中我們還可以使用它的變量和注釋。

# 井號開頭的行是一個注釋
# 設置 C 語言的編譯器
CC = gcc

# -g 增加調試信息
# -Wall 打開大部分警告信息
CFLAGS = -g -Wall

# 整理一下 main 依賴哪些目標文件
MAINOBJS = main.o array.o

.PHONY: clean

main: $(MAINOBJS)
    $(CC) $(CFLAGS) -o main $(MAINOBJS)

array.o: array.c array.h
    $(CC) $(CFLAGS) -c -o array.o array.c

main.o: main.c array.h
    $(CC) $(CFLAGS) -c -o main.o main.c

clean:
    rm -f $(MAINOBJS) main

上面這個例子已經是一個較為完整的Makefile了。以#開頭的是我們的注釋,我們在這里用注釋說明了我們定義的Makefile變量的用途。CC變量定義了編譯器,CFLAGS變量標記了編譯參數,MAINOBJS變量記錄了main依賴的目標文件。定義的變量可以直接通過$(變量名)進行使用。

總結

  • 一個 Makefile 可以包含多個規則,我們既可以每次在make后說明執行哪個功能,也可以通過定義的all來執行一系列的規則。
  • 在用gcc編譯時加上-Wall會顯示錯誤信息,Wall是用于顯示大部分警告信息的,編譯錯誤信息默認就會顯示。
  • Makefile其實描述了一系列轉為對象文件、聯編的過程,不使用make也是可以完成的。
  • Makefile中的變量是用$()的方式來用噠。

Makefile體驗

(1)
→ ~/project ls -l                                                                                 
                                                                                                  
total 16                                                                                          
-rw-r--r-- 1 user user 304 Sep 15 16:46 array.c                                                   
-rw-r--r-- 1 user user  87 Sep 15 16:46 array.h                                                   
-rw-r--r-- 1 user user 297 Sep 15 16:46 main.c                                                    
-rw-r--r-- 1 user user   0 Sep 15 16:46 main.h                                                    
-rw-r--r-- 1 user user 419 Sep 15 16:46 Makefile                                                  
→ ~/project                                                                                       
→ ~/project cat Makefile                                                                          
                                                                                                  
# 設置 C 語言的編譯器                                                                             
CC = gcc                                                                                          
                                                                                                  
# -g 增加調試信息                                                                                 
# -Wall 打開大部分警告信息                                                                        
CFLAGS = -g -Wall                                                                                 
                                                                                                                   
# 整理一下 main 依賴哪些目標文件                                                                  
MAINOBJS = main.o array.o                                                                         
                                                                                                  
.PHONY: clean                                                                                     
                                                                                                  
main: $(MAINOBJS)                                                                                 
        $(CC) $(CFLAGS) -o main $(MAINOBJS)                                                       
                                                                                                  
array.o: array.c array.h                                                                          
        $(CC) $(CFLAGS) -c -o array.o array.c                                                     
                                                                                                  
main.o: main.c array.h                                                                            
        $(CC) $(CFLAGS) -c -o main.o main.c                                                       
                                                                                                  
clean:                                                                                            
        rm -f $(MAINOBJS) main                                                                    
→ ~/project                                                                                      
(2)
→ ~/project make                

gcc -g -Wall -c -o main.o main.c                                                  
gcc -g -Wall -c -o array.o array.c                                    
gcc -g -Wall -o main main.o array.o                                     
→ ~/project                               
(3)
→ ~/project ./main              
                                                             
1 2 3 4 5 6 7 8 9 0                                     
數組元素和為: 45                                             
數組元素平均值為: 4.5                                      
                                                      
→ ~/project                                                 
(4)
→ ~/project make clean                   
                                                        
rm -f main.o array.o main             

(5)
→ ~/project            
→ ~/project ls -l     
                         
total 16                                             
-rw-r--r-- 1 user user 304 Sep 15 16:46 array.c          

命令行參數

之前,main函數一般都沒參數,對應在運行時,一般就直接輸入可執行的程序文件名(例如./main)。

但實際上main函數可以有參數。我們可以將任何過去無參數的main函數替換成下面這種有參數的main函數(不過考慮到我們并沒有利用,不寫是很正常的)。

int main(int argc, char **argv) {
    // ...
}

在這里,main函數有兩個參數,第一個參數是整數型,會傳入命令行參數的個數,程序運行時就可以接收到。第二個參數是char **,其中儲存了用戶從命令行傳遞進來的參數。

如果我們的程序可執行文件名為main,則在命令行中輸入./main hello world我們會得到argc3argv[0]./mainargv[1]helloargv[2]world。如果有更多參數也可以以此類推。

命令行參數默認都是空格分隔,但是如果我們希望包含空格的一個字符串作為參數,我們則需要在輸入參數時用引號將其包裹起來。

如果我們的程序可執行文件名為main,則在命令行中輸入./main "hello world" is my greet我們會得到argc5argv[0]./mainargv[1]hello worldargv[2]isargv[3]myargv[4]greet

任何被接收到的argv參數都可以被當做正常的字符串在代碼里使用。在很多程序的設計中,我們會需要根據接收到的參數來決定程序的執行方式,這時候,學會使用argcargv就顯得很重要了。在之后的課程中,你也會需要運用這一塊的知識,一定要學明白喔。

一些總結

  • 命令行讀入的參數是從命令行鍵入的可執行程序路徑開始計算。
  • 在main函數中用于接收命令行參數的函數參數中,第一個是命令行參數的個數。
  • 在int main(int argc, char **argv)中,argc就固定為 2 了,它取到的應該是命令行中鍵入的參數個數。

命令行參數

命令行參數是怎么獲取和使用的?

請先輸入 cat main.c 看一下我們當前所在目錄下的 main.c 文件。

image.png

看到,在這個 main.c 的文件中,我們的 main 函數獲取了命令行參數的個數 argc(整數型)和一系列參數(字符指針的指針,可以用訪問數組的形式訪問)。

這個程序將預期輸出命令行參數的數量,并且將每一個參數逐一列出。
接下來讓我們 make 一下,完成對這個程序的編譯。

image.png

完成了 make,就讓我們把它運行起來吧。請輸入 ./main 并運行起來這個程序,并在之后隨意輸上一些空格分隔開的字符串,例如:

./main I feel better after this

我們程序中的argc 接受到的參數一共是幾個,它們分別對應了我們在終端中輸入的哪一部分的內容呢。

image.png

文件操作

之前課程中,我們學習、設計的所有程序都是從標準輸入進行讀取、向標準輸出進行寫出的,操作系統為我們準備好了標準輸入、標準輸出的界面。在這節課中,我們將要學習如何從文件中進行讀取、如何向文件進行寫入。

在讀文件的時候我們需要先有一個可以讓我們訪問到文件的 文件指針(file pointer),它是一個FILE類型的指針。

我們可以通過下面的方式聲明一個文件指針。

FILE *fp;

這時候,如果我們希望對一個文件進行操作,我們需要先使用

fp = fopen(文件路徑, 訪問模式);

將文件指針和文件關聯起來,其中第一個參數是一個字符串,對應了我們希望訪問的文件路徑。第二個參數是訪問模式,它可以是表示只讀模式的"r",也可以是表示只寫模式的"w",還可以是在文件末尾追加的"a"

當我們將文件指針和文件關聯起來后,我們就可以通過fgetc(fp);獲得當前指針之后位置的一個字符了,每獲得一個字符,指針會向后移動一個字符(如果到達文件尾部則會返回EOF)。

我們這時通過fputc('c', fp);的方式將字符'c'寫入到fp關聯的文件內了。

了解到這些信息后,我們就可以實現將一個文件復制到另一個文件內的函數了,例如:

void filecopy(FILE *in_fp, FILE *out_fp) {
    char ch;
    while ((ch = fgetc(in_fp)) != EOF) {
        fputc(ch, out_fp);
    }
}

這個函數接收的兩個參數都是文件指針。這個函數會通過一個可讀模式的文件指針逐字符地讀取,并且通過一個可寫模式的文件指針逐字符地將所有字符寫出,從而起到復制文件內容的作用。

你需要注意,在給文件指針進行命名的時候,要避開 stdin、stdout 和 stderr 這三個名稱。因為這三個名稱其實已經用于標準輸入、標準輸出、標準錯誤的文件指針。

你可能會問了,那我們看到的 stdinstdoutstderr的這三個文件指針可以直接使用嗎?回答是肯定的。

我們是通過 fgetc(stdin);獲得來自標準輸入的字符,也可以通過fputc(ch, stdout);fputc(ch, stderr);將變量 ch中的字符輸出到標準輸出或標準錯誤中的。

除了fgetc和fputc之外,我們還可以使用fscanf和fprintf函數。這兩個函數都很像我們已經很熟悉的scanf和printf函數,只是不過,scanf和printf 可以被看作 fscanf和fprintf 的特例。

我們使用 fscanf 從文件指針in_fp進行讀取時,可以寫成:

fscanf(in_fp, "%c", &a);

而如果我們寫

fscanf(stdin, "%c", &a);

這將完全與下面直接使用 scanf 的方式等價。

scanf("%c", &a);

類似地,我們使用fprintf向文件指針out_fp進行寫出時,可以寫成:

fprintf(out_fp, "%c", a);

而如果我們寫

fprintf(stdout, "%c", a);

這將完全與下面直接使用 printf的方式等價。

printf("%c", a);

在使用文件并且確定不再繼續使用后,我們要通過下面所示的方式將文件指針fp與文件的關聯斷開。你可以將它視為和fopen相反的一個操作。

fclose(fp);

如果你不在程序中使用fclose,程序正常結束時,程序會為所有打開的文件調用fclose

stdinstdout其實也是被打開的文件指針,如果你覺得用不到的話,其實也是可以使用fclose將他們關閉掉的。你可以自己試一試,關閉 stdinstdout 會對我們以前寫過的程序帶來什么樣的影響呢?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,283評論 6 530
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 97,947評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,094評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,485評論 1 308
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,268評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,817評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,906評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,039評論 0 285
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,551評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,502評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,662評論 1 366
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,188評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,907評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,304評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,563評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,255評論 3 389
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,637評論 2 370

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,775評論 18 139
  • 動態鏈接,在可執行文件裝載時或運行時,由操作系統的裝載程序加載庫。大多數操作系統將解析外部引用(比如庫)作為加載過...
    小5筒閱讀 5,532評論 0 3
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 12,189評論 2 33
  • 1.簡介 GCC 的意思也只是 GNU C Compiler 而已。經過了這么多年的發展,GCC 已經不僅僅能支持...
    Leon_Geo閱讀 724評論 0 4
  • 動態調用動態庫方法c/c++linuxwindows 關于動態調用動態庫方法說明 一、 動態庫概述 1、 動態庫的...
    KINGZ1993閱讀 13,932評論 0 10