我的NDK之旅-,NDK之旅-
我的NDK之旅-,NDK之旅-
前言
jni介绍
1. Java Native Interface,即 Java本地接口
2. 通过JNI可以实现java和本地代码之间相互调用
即在 Java代码 里调用 C、C++等语言的代码 或 C、C++代码调用 Java 代码
3. JNI是 Java 调用 Native 语言的一种特性
JNI 是属于 Java 的,与 Android 无直接关系
4. 为什么使用JNI
- Java 一处编译到处运行
- ①java运行在虚拟机上 JNI可以扩展java虚拟机的能力 让java代码可以调用驱动
- ②java是解释型语言 运行效率相对较低 C/C++的效率要高很多 通过jni把耗时操作方法C/C++可以提高java运行效率
- ③ java代码编译成的.class 文件安全性较差, 可以通过jni 把重要的业务逻辑放到c/c++去实现,c/c++反编译比较困难 安全性较高
ndk介绍
1. 定义:Native Development Kit,是 Android的一个工具开发包
NDK是属于 Android 的,与Java并无直接关系
2. 作用:快速开发C、 C++*的动态库,并自动将so和应用一起打包成 APK
即可通过 NDK在 Android中 使用 JNI与本地代码(如C、C++)交互*
应用场景:在Android的场景下 使用JNI
总结
JNI :使用java语言调用Native(C,C++等其他)语言。
NDK : 在Android 中使用jni开发的方法
c语言基础
在JNI开发中需要用到的c语言基础
c的hello world 实现
#include<stdio.h> // 头文件
#include<stdlib.h>
/**
*/
main(){
printf("helloworld!\n"); // 输出
system("pause"); //system执行windows的系统命令
}
c与java 基本数据类型长度(字节) 比较
数据类型 | java | c |
---|---|---|
boolean | 1 | 无 |
byte | 2 | 1 |
char | 2 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long | 8 | 4 |
float | 4 | 4 |
double | 8 | 8 |
- signed 有符号数 最高位是符号位 可以表示负数 但是表示的最大值相对要小
- unsigned 无符号数 最高位是数值位 不可以表示负数 表示的最大值相对要大
- signed unsigned 只能用来修饰整形变量 char short int long
- C没有 boolean byte C用0和非0表示false true
- void 用在函数无返回和指针
c没有string 使用char类型的数组表示
C字符串
- C没有String类型 C的字符串实际就是字符数组
- C数组定义 [ ]只能再变量名之后
C字符串两种定义方式
char str[] = {'h','e','l','l','o','\0'};//注意'\0'字符串结束符 不以'\0'有可能出现乱码,无下标越界 char str[] = "你好"; //这种定义方式不用写结束符 可以表示汉字
- char* str 也表示字符串
c的输出函数
c使用占位符输出
1. 占位符对应数据类型
占位符 | 对应类型 |
---|---|
%d | int |
%ld | long int |
%lld | long long |
%hd | short |
%c | char |
%f | float |
%lf | double |
% u | 无符号数 |
%x | 十六进制输出 |
%o | 八进制输出 |
%s | 字符串 |
* 占位符不要乱用 要选择正确的对应类型 否则可能会损失精度
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 是地址 *pointer 是地址的值
*pointer = 456;
printf("i的值是%d\n",i);
system("pause");
- 指针常见错误
- 声明了指针变量后 未初始化直接通过*p 进行赋值操作 运行时会报错
- 未赋值的指针称为野指针
- 指针类型错误 如int* p 指向了double类型的地址, 通过指针进行读取操作时,读取值会出错
- 声明了指针变量后 未初始化直接通过*p 进行赋值操作 运行时会报错
值传递和引用传递(交换两个数的值)
- 引用传递本质是把地址传递过去
所有传递其实本质都是值传递,引用传递其实也是传递一个值,但是这个值是一个内存地址
*示例代码
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);
//***p3= **p2 = *p = i;
数组和指针的关系
- 数组占用的内存空间是连续的
- 数组变量保存的是第0个元素地址,也就是首地址
- *(p + 1):指针位移一个单位,一个单位是多少个字节,取决于指针的类型
指针的长度
不管变量的类型是什么,它的内存地址的长度一定是相同的
* 类型不同只决定变量占用的内存空间不同
* 32位环境下,内存地址长度都是4个字节,所以指针变量长度只需4个字节即可
//因为 一个字节占8位 32/8 = 4 ; 以此类推 64位是 8个字节
* 区分指针类型是为了指针位移运算方便
堆栈概念 静态内存分配 动态内存分配
- 栈内存
- 系统自动分配
- 系统自动销毁
- 连续的内存区域
- 向低地址扩展
- 大小固定
- 栈上分配的内存称为静态内存
- 静态内存分配
- 子函数执行完,子函数中的所有局部变量都会被销毁,内存释放,但内存地址不可能被销毁,只是地址上的值没了
- 堆内存
- 程序员手动分配
- java:new
- c:malloc
- 空间不连续
- 大小取决于系统的虚拟内存
- C:程序员手动回收free
- java:自动回收
- 堆上分配的内存称为动态内存
- 程序员手动分配
结构体
- 结构体中的属性长度会被自动补齐,这是为了方便指针位移运算
- 结构体中不能定义函数,可以定义函数指针
- 程序运行时,函数也是保存在内存中的,也有一个地址
结构体中只能定义变量
函数指针其实也是变量,它是指针变量
- 函数指针的定义 返回值类型(*变量名)(接收的参数);
- 函数指针的赋值: 函数指针只能指向跟它返回值和接收的参数相同的函数
- 长度大于或等于所有属性的长度的和,等于属性最长长度的整数倍
“`
typedef struct Student{
int age; //8
int score; // 4
char sex; //1
} stud;
## 联合体
* 长度等于联合体中定义的变量当中最长的那个
* 联合体只能保存一个变量的值
* 联合体共用同一块内存
union u{
int num; //4
double d; //8
}
## 枚举
enum weekday{
MON=9, TUE, WEND,THUR,FRI,SAT,SUN
};
main(){
enum weekday day = MON;
printf(“day= %d”,day);
system(“pause”);
}
“`
typedef
示例 :typedef int i; //将int 表示为 i
宏定义#define
#define PI 3.141592654 // 将 3.141592654 用PI表示
相关文章
- 暂无相关文章
用户点评