gcc :GNU編譯器套件(GNU Compiler Collection)是到了4.7,才真正支持c11的。
gcc & g++如今是gnu中最主要和最流行的c & c++編譯器 。
g++是將默認語言設爲c++,連接時自動使用C++標準庫而不用c標準庫 。
C++標準庫:http://www.runoob.com/cplusplus/cpp-standard-library.htmlhtml
調試選項 -g和-pglinux
優化選項 -O(0~3) 優化編譯、連接,-O0表示沒有優化,-O1爲缺省值,-O3優化級別最高;ios
目錄選項c++
錯誤與警告選項多線程
連接方式函數
其餘選項工具
在實際開發過程當中,各個模塊之間會涉及到一些通用的功能,好比讀寫文件,查找、排序。爲了減小代碼的冗餘,提升代碼的質量,能夠將這些通用的部分提取出來,作出公共的模塊庫。經過動態連接庫能夠實現多個模塊之間共享公共的函數。優化
建立動態庫,經過shared和fPIC編譯參數生產so動態連接庫文件。程序在調用庫函數時,只須要鏈接上這個庫便可。spa
/*caculate.h*/ #ifndef CACULATE_HEAD #define CACULATE_HEAD int add(int a, int b); int sub(int a, int b); int div(int a, int b); int mul(int a, int b); #endif /*caculate.c文件*/ #include "caculate.h" extern "C"{ int add(int a, int b) { return (a + b); } int sub(int a, int b) { return (a - b); } int div(int a, int b) { return (int)(a / b); } int mul(int a, int b) { return (a * b); } }
編譯生產libcac.so文件以下插件
g++ -fPIC -shared -o libxxx.so xx1.cpp xx2.cpp xx3.cpp //多個文件成成一個動態鏈接庫 g++ -fPIC -shared caculate.cpp -o libcac.so
#include <stdio.h> #include "caculate.h" int main(){ int a = 20; int b = 10; printf("%d + %d = %d\n", a, b, add(a, b)); printf("%d - %d = %d\n", a, b, sub(a, b)); printf("%d / %d = %d\n", a, b, div(a, b)); printf("%d * %d = %d\n", a, b, mul(a, b)); return 0; }
編譯生產可執行文件main以下: g++ main.c -o main -L./ -lcac
linux提供dlopen、dlsym、dlerror和dlcolose函數獲取動態連接庫的函數。
經過這個四個函數能夠實現一個插件程序,方便程序的擴展和維護。
#include <dlfcn.h> 以指定模式打開指定的動態連接庫文件,並返回一個句柄給 dlsym()的調用進程
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);//使用dlclose()來卸載打開的庫。 Link with -ldl.
flag在linux 下有三種解析方式 RTLD_LAZY 暫緩決定,等有須要時再解出符號 RTLD_NOW 當即決定,返回前解除全部未決定的符號。
做用範圍,可與解析方式經過「|」組合使用。
RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫解析。
RTLD_LOCAL: 與RTLD_GLOBAL做用相反,動態庫中定義的符號不能被其後打開的其它庫重定位。若是沒有指明是RTLD_GLOBAL仍是RTLD_LOCAL,則缺省爲RTLD_LOCAL。handle = dlopen(full_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
void _dlsym(void_handle,const char*symbol)
handle:由dlopen打開動態連接庫後返回的指針;
symbol:要求獲取的函數或全局變量的名稱。
#include <stdio.h> #include <dlfcn.h> #define DLL_FILE_NAME "libcac.so" typedef int (CAC_FUNC)(int, int); //using function = void()(int, int); //c++11 int main() { void *handle; CAC_FUNC func = NULL; char *error; int a = 30; int b = 5; handle = dlopen(DLL_FILE_NAME, RTLD_NOW); if(handle == NULL) { fprintf(stderr, "Failed to open libaray %s error:%s\n", DLL_FILE_NAME, dlerror()); return -1; } *(void **) (&func) = dlsym(handle, "add"); if(func == NULL){ printf("ERROR:%s:dlsym\n", dlerror()); return -1; } printf("%d + %d = %d\n", a, b, func(a, b)); func = (CAC_FUNC)dlsym(handle, "sub"); printf("%d + %d = %d\n", a, b, func(a, b)); func= (CAC_FUNC)dlsym(handle, "div"); printf("%d + %d = %d\n", a, b, func(a, b)); func = (CAC_FUNC)dlsym(handle, "mul"); printf("%d + %d = %d\n", a, b, func(a, b)); dlclose(handle); return 0; }
輸出:g++ maindl.cpp -o maindl -ldl
30 + 5 = 35 30 + 5 = 25 30 + 5 = 6 30 + 5 = 150
void *dlsym(void _handle, const char _symbol); 返回值爲void (void )&(func)是將函數指針的地址強制轉換void類型,而後使用取值,獲取dlsym的返回值 實際這個地方沒有必要這樣,函數指針原本就是地址,能夠直接用 func = dlsym(handle, "add");
一、函數的返回值若是是 void 類型的,則表示這個函數的執行結果是沒有返回值的; 二、函數的返回值若是是 void* 類型的,則表示返回一個內存地址,這個內存空間存放的數據類型是void類型的,即無類型的,也能夠說是萬能型的 三、在實際開發中,void* 使用時最終都要強制轉換成某種明確的數據類型