在当前短视频App、直播App火热的年代,但凡有多媒体必然有NDK的支持,对于一些C、C++的动态库,Android端可以通过NDK使用JNI与so库交互。
对于学习NDK来说,不需要掌握太多高深的C、C++知识,毕竟重心还是在Android端,所以不需要成为C、C++领域的大师,只需要有基本的了解即可。
1、Visual Studio创建第一个C++项目
在创建项目时,创建一个CMake项目;CMake项目主要使用来编写与平台无关的CMakeList.txt文件。
在创建CMake文件之后,会在项目中生成cpp
文件以及CMakeList.txt
文件。
2、C语言基础
(1)基本数据类型
在C语言中,基本数据类型主要有:int
(4字节)、char
(1字节)、long
(4字节)、short
(2字节),主要的区别在于有符号还是无符号,一般默认情况下,默认是signed
,有符号的;unsigned
,意为无符号的,取值范围是从0开始,没有正负号。
如果想要获取某个基本数据类型所占的字节,使用sizeof
。
int main()
{
long j = 10;
printf("%d\n", sizeof(j));
system("pause");
return 0;
}
int32_t
(int
):int类型的数据,占据4个字节;
int64_t
(long
long
java中long
类型占据的字节数):int
类型的64位数据,占据8个字节。
float
和double
和Java中的一致,float
占据4个字节,double
占据8个字节。
在c99中,引入了bool
类型,其实是int
类型,非0即为true,非null即为true。
关于格式化的问题:
对于基本的整型变量来说,在打印时需要使用占位符%d
,对于无符号的整型,使用%u
占位符;
占位符在SQL语句中出现过一次,当时是使用?来作为占位符,%d作为占位符,在后边会加上占位符的具体值。
printf("%d\n", sizeof(j));
这里sizeof(j)的值,就会被填充到%d的位置,最终输出sizeof(j)的值
例如在一个文件夹下存在3个文件,需要打印输出这3个文件的绝对路径,那么就可以使用占位符拼接字符串实现,
char str[100];
for (size_t i = 1; i <= 3; i++)
{
sprintf(str, "xxx/%d.text", i);
printf(% s\n, str);
}
最终的输出就是:
xxx/1.text
xxx/2.text
xxx/3.text
(2)数组
在C语言中,声明数组时,必须要声明数组的长度,或者显式的将数组元素排列出来,不能和java一样,可以先创建一个空数组。
int[5] a;
int[] a = { 1,2,3,4,5,6,7 };
(3)内存分配
和Java一样,一些基本数据类型,数组引用等,都会放在栈中,但也要防止栈溢出的问题。
对于堆内存,Java
对象通常是通过new
关键字,在堆内存中动态分配内存,但是在C语言中,是没有new关键字的,是通过malloc
。
如果在堆内存中,申请1M的内存,那么就可以通过下面的方式,使用j
指针来指向这个1M的堆内存空间:
void *j = malloc(1 * 1024 * 1024);
但是仅仅这样是可以的,还需要初始化;使用memset
就是将j
指针指向这块内存区域,初始化为0,长度为k。
void *j = malloc(1 * 1024 * 1024);
size_t k = 1 * 1024 * 1024;
memset(j, 0, k);
这样实现就不会出现OOM、栈溢出的问题。因为C语言不和Java一样,系统自动回收内存,需要开发者手动释放内存。
//释放内存
free(jj);
jj = 0;
除了malloc
之外,还有calloc
,使用calloc
可以动态申请内存并初始化为null(0)
,例如:
int *jj = (int*)calloc(10, sizeof(int));
此语法就是,动态申请了40字节的内存,初始值为null;
就等同于malloc的一下2行代码
int *jj = (int*)malloc(sizeof(int) * 10);
memset(jj,0,sizeof(int) * 10);
如果想要对malloc申请的内存进行调整,使用realloc调整,可扩容。
realloc(jj,sizeof(int) * 20);
(4)C的内存结构
C的内存结构主要分为:内核空间、栈、内存映射区、堆、BSS、数据区、代码区。
跟JVM类似的一些区域,功能也大致相同,这里说一些新的内容。
BSS:未被初始化的静态变量;
数据区:静态变量的存取区,类似于JVM的方法区
这两者也可以合称为方法区、静态区。
文本区:代码区
当从栈中申请内存时,是由高地址指向低地址;而在堆中申请内存时,是从低地址指向高地址。
在堆内存中申请内存时,使用malloc动态分配内存,内部有2种实现方式:brk、mmap
brk
:使得低位指针_edata指向高位,在堆中申请10K的内存空间,则_edata将会移动到10K的位置;
mmap
:选择一块合适的内存区域,如果申请一块100K的内存,那么就会在堆内存中获取一块100K的内存。
当使用malloc动态申请内存时,有一个阈值128K(该值可配置),当申请内存小于128K的时候,就会使用brk分配内存;如果大于128K时,将会使用mmap动态选择一块合适的内存。
brk相较于mmap的优势在于:只需要推指针即可,不需要从内存中寻找内存区域,更高效一些。
(5)C项目的组成
在生成的项目中,.cpp文件就是源文件,执行全部的代码;.h文件是头文件,可以在头文件中声明方法,在.c文件中实现,当然也可以在.h文件中实现。
#include "CMakeProject1.h"
在.c文件中,也包含这个头文件的引用,表明可以使用该头文件中的方法。