JNI 开发中 C / C++ 基础

what 什么是 JNI

JNI java native interface native 本地 java本地接口

jni可以看作是翻译, 实际上是一套协议

why 为什么要用JNI 

   *java 一处比编译到处运行

        * Java运行在虚拟机上, 但是无法调用底层驱动, JNI可以扩展java的虚拟机能力 让java代码可以调用驱动

        * java是解析型语言, 运行效率相对较低 C / C++ 的效率要高很多, 通过jni把耗时操作放在  c/ c++中提高java运行效率

        * java编译成的.class 文件安全性较差, 可以通过 jni 把重要的业务逻辑放到c/c++去实现, c/c++反编译比较困难, 安全            性较高

    * c历史悠久, 有大量优秀的开源类库

HOW 怎么用

    * java

    * c / c++ 能看懂, 会调用

    * JNI开发流程 NDK native develop kit


C基本语法

基本数据类型

  java            C
   byte  1字节   
boolean
char 2字节 char 1字节 int 4字节 int 4字节 short 2字节 short 2字节 long 8字节 long 4字节 float 4字节 float 4字节 double 8字节 double 8字节

C中有signed 和unsigned关键字, 用于标识有符号和无符号(只能用于整形 int char short long)

C没有byte 和 boolean  用 1 表示true 用 0表示 true

    

C输出函数:

printf("");

占位符

%d - int
%ld - long int
%lld - long long
%hd - 短整型
%c - char
%f - float
%lf - double
%u - 无符号数
%x - 十六进制输出 int 或者 short int
%o - 八进制输出
%s - 字符串

乱用可能会发生进度损失

定义字符串有两种方式,

char cArray[] = {'a','b','c','d', '你好','\0'};  //中文无法输出

必须指定 \0作为结束标志, 否则会输出不必要的地址, 不能输出中文

 char cArray[] = "abc你好"; 

不用指出结束位置, 可以输出中文


C的输入函数:

scanf("占位符", 内存地址);

&ad    //获取ad 引用的指针

注意:在接收输入 数组(字符串)时,系统不会检查下标越界问题, 有时候越界会使得超出部分覆盖掉旁边的数据, 使旁边的数据发生错误 (数组的结束符“\0”被存进内存时就是一个 int 的0) 


内存地址

指针

一般用16进制数标识一个内存地址

int* 关键字表示int类型的指针变量

&  关键字表示去内存地址

int* pointer = &i;    //ponter就是一个指针变量, 指针变量只能用于存放内存地址

*pointer  表示取出ponter对应内存地址的值(实际上是一个内存地址, 再对该内存地址取值)


指针异常:

1、野指针

//int* pointer;
//printf("pointer = %#x\n", pointer);

//*pointer = 123;    有异常, 如果pointer未初始化, 系统会随机分配一个内存地址给pointer, 此时是不允许修改这个内存地址的值的 

2、类型不匹配

int类型指针不能指向double或其他类型的内存地址


交换连个值:

在另外一个函数swap1(int i, int j)中修改main函数中的i和j, 值传递方式无法修改

因为swap1(int i, int j)中会生成另外一个内存空间去存放该函数的i和j, 函数内操作的i和j与main中的不是同一个i和j


可以通过引用传递的方式修改swap2(int* pointeri, int* pointerj)




返回多个值

C中不能返回数组, 也没有集合, 所以无法返回多个值

如果想要返回多个值, 则可以直接通过修改内存地址中值的方式

function(int* pointeri, int* pointerj){
*pointeri *= 2;  //直接修改传递过来指针指向内存地址中的值 (感觉相当于把i和j提取出来做成员变量,
// 让后在另外一个函数直接修改这个成员变量, 就不用返回, 再次使用时这个值就已经被改变了)
*pointerj *= 2; 


内存地址和指针的关系

数组实际上是一块连续的内存空间

取出数组首元素的指针

char array[] = {'1','2','3','4','\0'};

char* pointer = &array;    //取出的是数组首元素的指针

*(pointer+1) ---->  指针会指向数组的下一位

int  array2[] = {1,2,3,4};

int* pointer = &array;

*(pointer + 1)  ---->  指针也是指向数组的下一位, 虽然 int类型是占4位, 但是定义指针时会自动识别



指针变量的长度:

32位操作系统(编译器的系统版本)指针变量占4个字节

64位操作系统, 指针变量占8个字节

与指针的类型无关


多级指针:

一级: int* pointer1 = &i;

二级:int** pointer2 = &pointer1;

三级: int*** pointer3 = &pointer3;


静态内存分配(栈内存)

栈内存 系统统一分配, 统一回收

静态内存分配 栈内存大小固定 内存地址连续的 

内存分配方式有三种:

[1] 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量, static 变量。

[2] 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中 ,效率很高,但是分配的内存容量有限。

[3] 从堆上分配,亦称动态内存分配 。程序在运行的时候用 malloc 或 new 申请任意多少的内存,程序员自己负责在何时用 free 或 delete 释放内存。动态内存的生存期由程序员决定 ,使用非常灵活,但如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,频繁地分配和释放不同大小的堆空间将会产生堆内碎块。


结构体

c结构体 类似于java的class   用struct来声明c的结构体

结构的大小:大于等于结构体中每一个变量占的字节数的总和, 是字节数最大的变量的整数倍

结构体中不能定义函数, 但是有函数指针, 可以起到函数的作用

函数指针的定义  : 返回值( *函数指针变量名)(返回值);   void (*studypointer)();

                              两处的返回值要一致

调用指针函数:  结构体引用变量 .  指针变量名();     stu.studypointer();

结构体指针(*stuPointer)也可以获取成员变量值: (*stuPointer).age)

也可以用结构体的一级指针, 通过间接引用符来获取结构体的成员: stuPointer ->age


联合体

与结合体相似, 用union关键字定义

大小:取决于成员中 占用内存最大的那个

特点:所有成员使用同一块内存, 后面定义的会覆盖前面的

使用场景:嵌入式设备中节省内存


枚举

定义关键字:enum


自定义类型

语法   typedef 数据类型 别名

例如: typedef int i;    以后就直接可以用 i 代表int类型的关键字

            typedef  struct Student{

            } stud ;             //这里的stud就是自定义类型, 代表这个结构体

实际上是对类型起别名, 在JNI中使用自定义类型(起别名)的方式, 增加了代码的可读性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值