JNI开发——C语言基础二
函数指针:
cal就是函数指针,函数名plus是这个函数的首地址,所以可以将函数赋值给对应类型的函数指针cal。
函数指针可以强转,有点java多态的感觉。为什么可以强转呢?
不管是 int 类型的指针还是 char 类型的指针还是其他类型的指针,指针变量都是4个字节。从void* ——> int* / char* / float* 无非就是从指针所指向的地址中去内容时,是取连续的4个字节还是1个字节的不同。
int (*cal) (int *a,int* b);这是函数指针。
int * p(int *a,int *b); 这是返回值为int*指针的函数。
内存分配:
申请一个40M的数组
运行之后:
栈溢出内存分为三个区:
程序区:存储程序的二进制文件
静态存储区:存储全局变量和静态变量。(如:int const a = 10;)
动态存储区:
堆区:用于程序动态分配的内存。
栈区:编译器自动分配和释放。栈内存不会很大(上面例子的数组的内存就是在栈中分配的)
int array[10] 这个array是一个常量是一个地址,常量不可以修改。数组的改变是修改了数组里面存的值而不是修改数组本身。
malloc:
int *p = (int*)malloc(1024*10);
void* malloc(size_t size) 动态申请内存,内存大小的单位是字节,申请的是连续的内存空间。
如上图:假如使用malloc申请一个40KB的内存,就会在这个四个内存块中寻找有40KB这么大的内存空间的,就会在50KB这里获得内存。如果申请失败返回值是Null。
calloc:
void* calloc(size_t _count,size_t _size);
申请count个大小为size的内存空间,连续空间是size而不是count*size,同时他会初始化空间里面的值全部为0。
不管是malloc 还是calloc动态申请的内存的内存都需要释放,释放free(p);然后还要p=NULL,避免出现野指针,申请和释放要一 一对应。
字符串:
C中并没有java的String来表示字符串。
方式1:
运行结果:
ch数组的最后会默认添加 ‘\n’,会以这个作为字符串结束符,主意数组里面是单引号。
方式2:
运行结果:
在字符串的后面会添加很多的乱码,要输出正确的字符串需要手动的添加结束符。
这样才能输出正确的结果。
方式3:
这个也能正确输出字符串,还可以通过数组修改字符串中的某一个字符。如:
运行结果:
方式4:
这个也可以跟上面方式3一样修改某一个字符。
方式5:
这个方式字符串不可以修改,因为jni字符串是一个常量,常量在静态区,所以不能修改,ch是指向静态区地址的指针。
方式6:
如果想要修改jni中的某一个字符串怎么办呢?首先不能在常量区
jni这个字符串复制一份然后赋值给ch所指的内存空间。
字符串的一些操作:
strcat:字符串的拼接
运行结果:
不可以直接传mes 和des 拼接。
char * strchr(char *str,char c):在一个字符串中查找给定字符的第一个匹配之处。
int strcmp(char *str1,char *str2): 以大小写不敏感的方式比较字符串。
结构体:
一系列不同类型的数据的结合。
结构体的申明:
局部变量的结构体
全局变量的结构体
当然也可以使用 struct Student stu;这样放在main方法外面定义一个全局的。
匿名结构体:
匿名结构体匿名结构体只有在这一个地方可以用不可能在多出使用这个结构体,可以锁定结构体的数量。
结构体的初始化:
方式1:
方式2:
方式3:
结构体数组:
结构体数组的申明和初始化:
方式1:
这里的结构体初始化也可以不用加struct,直接用Student stu[2] = {{“米K”,20},{“lili”,25}};加上会更好更容易阅读,数据中的{}来隔开数据 也可以不用写,写了方便阅读和寻找错误。
方式2:
这里面的stu[i].name可以写成stu—>name 如:
结构体指针:
结构体指针的初始化:
方式1:
方式2:
memset是初始化st为首地址的内存,初始化值为0,长度为sizeof()*3;
运行结果:
结构体中添加函数指针:
运行结果:
结构体中添加结构体指针: