環境準備
可以選擇使用 VS2013開發,但是這個家夥比較重量級,是以我們還有一個選擇就是使用 Clion,如果隻使用 Clion需要配置 MinGW環境。
VS2013
下載下傳連結:https://pan.baidu.com/s/1uOMk6LEAazBG5YQf_R6Ssg 提取碼:3ts6
Clion
Jetbrains旗下産品之一,主要用來開發C/C++,軟體相比VS來說輕巧很多,官方下載下傳連結:http://www.jetbrains.com/clion/?fromFooter
Clion的安裝就是傻瓜式的下一步下一步,這裡就不再贅述,太侮辱大家智商了,哈哈哈~ 安裝好Clion之後,别急着運作,得先裝MinGW,因為它才是真正執行C/C++程式的東東。
MinGW
連結:http://sourceforge.net/projects/mingw/files/
點選下載下傳按鈕:

運作安裝包:
點選 Install:
點選Continue,等待安裝完成之後,再點Continue:
安裝完成之後,需要下載下傳相關包的支援,如下圖所示:點選左側的 Basic Setup,勾選所有包:
點選 Installation→Apply Changes:
然後就是漫長的等待,大約半個小時左右後,右側的包前面的框框變綠了,說明MinGW環境OK了。
第一個C程式
打開Clion,打開File→Settrings→Build,Execution,Deployment→Toolchains,可以看到 Clion會自動比對 MinGW,因為我本地安裝了 VS2013,是以這裡會同時出現 MinGW和 VS,随便選擇一個即可。
找到工具欄中的 File→New Project:
接着我們選擇C Executable,再選擇自己存放C工程的目錄,C标準一般選擇C99,然後點選 Create。
工程建立好之後,預設會建立一個 main.c檔案,等工程加載完成之後,點選運作按鈕即可。
PS:Clion隻有30天的免費試用時間,點選加入我的安卓技術訓練營,群共享中有無限試用的方法。
初識NDK
NDK是什麼
- NDK(C/C++) <-------------------> SDK(Java)性質是一樣的
- 定義:Native Development Kit,是 Android的一個工具開發包
- 作用:快速開發C、 C++的動态庫,并自動将so和應用一起打包成 APK
- 提供了把.so和.apk打包的工具
- 提供了交叉編譯器,用于生成特定的CPU平台動态庫
- 提供了很多很多的native支援,就相當于SDK提供了很多上層的支援一樣
NDK特點
- 運作效率高
- 代碼安全性高
- 功能拓展性好
- 易于代碼複用和移植
NDK能做什麼
打開支付寶APK,微信APK,等等,裡面就有很多native庫
NDK的學習由哪些内容所組成
第一階段:C語言的學習,C++語言的學習,JNI的學習。
第二階段:CMake的學習,Linux基本操作,Linux Shell腳本程式設計。
第三階段:各種實戰(身份證識别,MMKV元件,QQ變聲 等)。
第四階段:FFmpeg視訊播放器項目,RTMP直播流。
第五階段:OpenCV人臉定位,OpenGL視訊處理,OpenGL視覺效果。
目前先按這五個階段一步一步來。
C語言基礎
解讀第一個程式
#include <stdio.h>
//#include "stdio.h"
//<>表示尋找系統庫;如果用“”,則會先去尋找自定義的庫,找不到才會去找系統的庫
//.h .hpp 是頭檔案,聲明檔案
//.c .cpp 是實作檔案
int main() {
printf("Hello world!");
return 0;//0表示程式執行完成後正常退出
}
基本資料類型
#include <stdio.h>
// 基本資料類型
int main() {
int i = 100;
double d = 200;
float f = 300;
long l = 400;
short s = 500;
char c = 'a';
// 字元串
char *str = "Luffy";
// 不是随便列印的,需要占位
printf("i的值是:%d\n", i); // d == decimal
printf("d的值是:%lf\n", d); // lf == long float
printf("f的值是:%f\n", f); // f == float
printf("l的值是:%d\n", l); // d == decimal
printf("s的值是:%d\n", s); // s == short
printf("c的值是:%c\n", c); // c == char
printf("字元串:%s\n", str); // s == string
getchar();//阻塞程式
return 0;
}
關于getchar的作用移步這裡:getchar()作用
#include <stdio.h>
/**
* 基本類型占用的位元組數(後續過程中,非常常用的) sizeof擷取位元組數
* 因為有些基本資料類型的所占位元組數與作業系統有關,比如32位的系統int
* 可能占2個位元組,64位的占4個
*/
int main() {
// int 占幾個位元組 == 4
// double 占幾個位元組 == 8
// char 占幾個位元組 == 8
printf("int 資料類型所占的位元組數:%d\n", sizeof(int));// 4
printf("double 資料類型所占的位元組數:%d\n", sizeof(double));// 8
printf("char 資料類型所占的位元組數:%d\n", sizeof(char));// 1
return NULL; // NULL == 0
}
指針
概念
#include <stdio.h> // C99 标準庫
// 位址概念
// Java ------ 萬物皆對象
// C C++(對象) ------ 萬物皆指針
// Linux ------ 萬物皆檔案
int main() {
// 指針 == 位址
// %p == 位址輸出的占位
// & == 取出位址
int number = 100000;
printf("number變量的位址是:%p\n", &number); // 位址 == 0061FF1C
return NULL;
}
PS:解決列印語句在控制台輸出中文亂碼問題,輕按兩下shift,輸入 File encoding修改編碼格式。
取出指針儲存的值
#include <stdio.h>
int main() {
int number_int = 100;
double number_double = 200;
printf("number_int的值是:%d\n", number_int);
printf("number_double的值是:%lf\n", number_double);
// * 取出number_int位址所對應的值 == 100
// 指針取出值
// 既然任何變量都是位址,可以使用位址擷取值
printf("number_int的值是:%d\n", *(&number_int));
printf("number_double的值是:%lf\n", *(&number_double));
// ================ 難度更新
// 在這裡,指派号左邊的星号是為了聲明指針變量
int *intP = &number_int;
double *doubleP = &number_double;
// 輸出 100 和 200
printf("number_int的值是:%d\n", *intP);//printf格式化輸出語句中,後面的星号是用來取位址的
printf("number_double的值是:%lf\n", *doubleP);
// 概念
/**
如果你去上網查詢,指針的文章,就會發現,一些專業術語,導緻大學老師一直說不清楚,成功勸退很多學生放棄:
記憶體位址變量,記憶體位址别名,指針,指針變量,指針别名,.... 一大段的專業術語 ...
了解: 大道至簡 (化繁為簡)
記憶體位址 == 指針
指針 == 記憶體位址
int * ------ (int類型的指針),double * ------ (double類型的指針)
指針别名,指針變量 == 就是一個變量而已,隻不過 是指針的 變量 而已
上面代碼中的 intP 和 doubleP 就是指針變量
*/
return NULL;
}
通過指針修改值
#include <stdio.h>
// 通過指針(位址)修改值
int main() {
int i = 100;
// p:我隻接收位址,你給我一個100,不規範
// int * p = i;
int * p = &i;
i = 200;
printf("i的值:%d\n", i);
*p = 300;//取出指針 p存放的資料,然後用 300覆寫給這個資料的原始值
printf("通過指針修改i的值:%d\n", i);
return 0;
}
函數中的值傳遞和位址傳遞
#include <stdio.h>
// C語言不允許函數重載 Java可以,C++可以
//void change(int i); // 先聲明 ------ 這樣的是值傳遞,形參相當于change函數中的局部變量
void change(int *i); // 先聲明 ------ 這樣是位址傳遞
//調用函數修改值,傳參需要用指針
int main() {
int i = 100;
// change(i);
change(&i);
printf("main中i的位址%p,i的值%d\n", &i, i);
/*
int * i; 定義指針
*i = 666; 取出記憶體位址所對應的值修改成666
*/
return 0;
}
// 函數不能寫在 main的下面,會報錯
// void change(int i) {}
// 再實作
//void change(int i) {
//
// printf("change記憶體位址:%p\n", &i);
//
// i = 200;
//}
// 再實作
// 使用指針 來修改
void change(int *i) {
printf("change中 i 的記憶體位址:%p\n", i);
*i = 666;
}
#include <stdio.h>
// 由于C語言不支援函數重載,是以聲明的函數,不需要寫參數 (隻要函數名一樣,
// 就會報錯,即使傳回值不一樣也不行)
//int changeAction();
void changeAction();
int main() {
int a = 100;
int b = 200;
changeAction(&a, &b);
printf("交換完成後的效果:a = %d,b = %d\n", a, b);
return 0;
}
// 隻接收指針(記憶體位址) 記憶體位址 == 指針
void changeAction(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}