android下JNI開發--01

what 什麼是JNI

  • JNI java native interface native本地 java本地接口
  • 通過JNI可以實現java和本地代碼之間相互調用
  • jni可以看做是翻譯 實際上就是一套協議

why 爲什麼要用JNI

  • Java 一處編譯到處運行
    • ①java運行在虛擬機上 JNI可以擴展java虛擬機的能力 讓java代碼可以調用驅動
    • ②java是解釋型語言 運行效率相對較低 C/C++的效率要高很多 通過jni把耗時操作方法C/C++可以提高java運行效率
    • ③ java代碼編譯成的.class 文件安全性較差, 可以通過jni 把重要的業務邏輯放到c/c++去實現,c/c++反編譯比較困難 安全性較高
  • C歷史悠久 1972年C 通過JNI可以調用優秀的C開源類庫

How 怎麼用JNI

  • java
  • c/c++ 能看懂 會調用
  • JNI開發流程 NDK native develop kit

C基本語法

CHelloWorld

#include<stdio.h>    // 相當於 java的import .h c的頭文件 stdio.h standard io 標準輸入輸出 
#include<stdlib.h>   // stdlib standard library 標準函數庫    java.lang 
/**
*/
main(){    // public static void main(String[] args)
       printf("helloworld!\n");  //System.out.println();   "\n"換行符 
       system("javac Hello.java");
       system("java Hello");
       system("notepad");
       system("pause"); //system執行windows的系統命令 
       } 

C的基本數據類型

  • java基本數據類型
    boolean 1
    byte 1
    char 2 char 1個字節
    short 2 short 2
    int 4 int 4
    long 8 long 4
    float 4 float 4
    double 8 double 8

char, int, float, double, long, short, signed, unsigned, void
* signed 有符號數 最高位是符號位 可以表示負數 但是表示的最大值相對要小
* unsigned 無符號數 最高位是數值位 不可以表示負數 表示的最大值相對要大
* signed unsigned 只能用來修飾整形變量 char short int long
* C沒有 boolean byte C用0和非0表示false true

C的輸出函數

%d  -  int
%ld – long int
%lld - long long
%hd – 短整型
%c  - char
%f -  float
%lf – double
%u – 無符號數
%x – 十六進制輸出 int 或者long int 或者short int
%o -  八進制輸出
%s – 字符串
  • 佔位符不要亂用 要選擇正確的對應類型 否則可能會損失精度
  • C字符串

    • C沒有String類型 C的字符串實際就是字符數組
    • C數組定義 [ ]只能再變量名之後
    • C字符串兩種定義方式

      char str[] = {'h','e','l','l','o','\0'};//注意'\0'字符串結束符
      char str[] = "你好"; //這種定義方式不用寫結束符 可以表示漢字
      

C的輸入函數

  • scanf(“佔位符”, &地址);
  • & 取地址符
  • C字符串不檢查下標越界 使用時要注意

內存地址的概念

  • 聲明一個變量,就會立即爲這個變量申請內存,一定會有一個對應的內存地址
  • 沒有地址的內存是無法使用的
  • 內存的每一個字節都有一個對應的地址
  • 內存地址用一個16進制數來表示
  • 32位操作系統最大可以支持4G內存
    • 32位系統的地址總線爲32位,也就是說系統有2^32個數字可以分配給內存作爲地址使用

指針入門 **

 int i = 123;
       //一般計算機中用16進制數來表示一個內存地址 
       printf("%#x\n",&i); 
       //int* int類型的指針變量  pointer指針  指針變量只能用來保存內存地址
       //用取地址符&i 把變量i的地址取出來 用指針變量pointer 保存了起來
       //此時我們可以說 指針pointer指向了 i的地址 
       int* pointer = &i;   
       printf("pointer的值 = %#x\n",pointer);
       printf("*pointer的值%d\n",*pointer);
       *pointer = 456;
       printf("i的值是%d\n",i);
       system("pause"); 

* 指針常見錯誤
* 聲明瞭指針變量後 未初始化直接通過*p 進行賦值操作 運行時會報錯
* * 未賦值的指針稱爲野指針
* 指針類型錯誤 如int* p 指向了double類型的地址, 通過指針進行讀取操作時,讀取值會出錯

指針的練習

  • 值傳遞和引用傳遞(交換兩個數的值)

    • 引用傳遞本質是把地址傳遞過去
    • 所有傳遞其實本質都是值傳遞,引用傳遞其實也是傳遞一個值,但是這個值是一個內存地址

      void swap(int* p, int* p2){
          int temp = *p;
          *p = *p2;
          *p2 = temp; 
      }
      main(){
          int i = 123;
          int j = 456;
          //將i, j的地址傳遞過去
          swap(&i,&j);
          printf("i = %d, j = %d", i, j);
      }
      
  • 返回多個值
    • 把地址作爲參數傳入函數中,當函數執行完畢時,參數的值就已經被修改了

多級指針

  • int* p; int 類型的一級指針 int** p2; int 類型的二級指針
  • 二級指針變量只能保存一級指針變量的地址
  • 有幾個* 就是幾級指針 int*** 三級指針
  • 通過int類型三級指針 操作int類型變量的值 ***p

        int i = 123;
        //int類型一級指針 
        int* p = &i;
        //int 類型 二級指針 二級指針只能保存一級指針的地址 
        int** p2 = &p;
        //int 類型 三級指針  三級指針只能保存二級指針的地址 
        int*** p3 = &p2;
        //通過p3 取出 i的值
        printf("***p3 = %d\n", ***p3);
    
  • 多級指針案例 取出子函數中臨時變量的地址

數組和指針的關係

  • 數組佔用的內存空間是連續的
  • 數組變量保存的是第0個元素地址,也就是首地址
  • *(p + 1):指針位移一個單位,一個單位是多少個字節,取決於指針的類型

指針的長度

  • 不管變量的類型是什麼,它的內存地址的長度一定是相同的
  • 類型不同只決定變量佔用的內存空間不同
  • 32位環境下,內存地址長度都是4個字節,所以指針變量長度只需4個字節即可
  • 區分指針類型是爲了指針位移運算方便

堆棧概念 靜態內存分配 動態內存分配

  • 棧內存
    • 系統自動分配
    • 系統自動銷燬
    • 連續的內存區域
    • 向低地址擴展
    • 大小固定
    • 棧上分配的內存稱爲靜態內存
  • 靜態內存分配
    • 子函數執行完,子函數中的所有局部變量都會被銷燬,內存釋放,但內存地址不可能被銷燬,只是地址上的值沒了
  • 堆內存
    • 程序員手動分配
      • java:new
      • c:malloc
    • 空間不連續
    • 大小取決於系統的虛擬內存
    • C:程序員手動回收free
    • java:自動回收
    • 堆上分配的內存稱爲動態內存

結構體

  • 結構體中的屬性長度會被自動補齊,這是爲了方便指針位移運算
  • 結構體中不能定義函數,可以定義函數指針
  • 程序運行時,函數也是保存在內存中的,也有一個地址
  • 結構體中只能定義變量
  • 函數指針其實也是變量,它是指針變量
  • 函數指針的定義 返回值類型(*變量名)(接收的參數);
  • 函數指針的賦值: 函數指針只能指向跟它返回值和接收的參數相同的函數

聯合體

  • 長度等於聯合體中定義的變量當中最長的那個
  • 聯合體只能保存一個變量的值
  • 聯合體共用同一塊內存
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章