天天看點

NDK開發C語言基礎(第一天)

環境準備

可以選擇使用 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/

點選下載下傳按鈕:

NDK開發C語言基礎(第一天)

運作安裝包:

NDK開發C語言基礎(第一天)

點選 Install:

NDK開發C語言基礎(第一天)

點選Continue,等待安裝完成之後,再點Continue:

NDK開發C語言基礎(第一天)

安裝完成之後,需要下載下傳相關包的支援,如下圖所示:點選左側的 Basic Setup,勾選所有包:

NDK開發C語言基礎(第一天)

點選 Installation→Apply Changes:

NDK開發C語言基礎(第一天)

然後就是漫長的等待,大約半個小時左右後,右側的包前面的框框變綠了,說明MinGW環境OK了。

NDK開發C語言基礎(第一天)

第一個C程式

打開Clion,打開File→Settrings→Build,Execution,Deployment→Toolchains,可以看到 Clion會自動比對 MinGW,因為我本地安裝了 VS2013,是以這裡會同時出現 MinGW和 VS,随便選擇一個即可。

NDK開發C語言基礎(第一天)

找到工具欄中的 File→New Project:

NDK開發C語言基礎(第一天)

接着我們選擇C Executable,再選擇自己存放C工程的目錄,C标準一般選擇C99,然後點選 Create。

NDK開發C語言基礎(第一天)

工程建立好之後,預設會建立一個 main.c檔案,等工程加載完成之後,點選運作按鈕即可。

NDK開發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能做什麼

NDK開發C語言基礎(第一天)

打開支付寶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修改編碼格式。

NDK開發C語言基礎(第一天)

取出指針儲存的值

#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;
}           

繼續閱讀