• C语言/指针


    JNI java本地开发接口

    JNI 是一个协议

    这个协议用来沟通java代码和外部的本地代码(c/c++).

    通过这个协议,java代码就可以调用外部的c/c++代码

    外部的c/c++代码也可以调用java代码

    * 输出

    #include <stdio.h> //standard input output
    #include <stdlib.h>
    
    main(){
           printf("小志的逗比精神永存
    ");
           system("pause"); 
    }

    * C调用java的hello

    public class Hello
    {
        public static void main(String[] dd){
            System.out.println("hello from java");
        }
    }
    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           printf("hello from c
    "); 
           system("java Hello");
           system("pause"); 
    }

    * C的基本数据类型

    char, int, float, double, long, short, signed, unsigned

    #java的基本数据类型长度
    * byte:1
    * short:2
    * int:4
    * long:8
    * boolean:1
    * char:2
    * float:4
    * double:8

    #c的基本数据类型长度
    * short:2
    * int:4
    * long:4
    * char:1
    * float:4
    * double:8

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           //char, int, float, double, long, short, signed, unsigned
           
           int i =3;
           char c = 'a';
           long long ago = 12314324;
           short int i2 = 2;
           long int i3 = 3243;
           //printf("i的值为%d
    ", i);
           
           printf("char的长度:%d
    ", sizeof(char));
           printf("int的长度:%d
    ", sizeof(int));
           printf("float的长度:%d
    ", sizeof(float));
           printf("double的长度:%d
    ", sizeof(double));
           printf("long的长度:%d
    ", sizeof(long));
           printf("short的长度:%d
    ", sizeof(short));
           printf("long long的长度:%d
    ", sizeof(long long));
           printf("short int的长度:%d
    ", sizeof(short int));
           printf("long int的长度:%d
    ", sizeof(long int));
           
           system("pause"); 
    }

    * 输出函数

    #include <stdio.h>
    #include <stdlib.h>
    /*
    %d  -  int
    %ld – long int
    %hd – 短整型
    %c  - char
    %f -  float
    %lf – double
    %u – 无符号数
    %x – 十六进制输出 int 或者long int 或者short int
    %o -  八进制输出
    %s – 字符串
    */
    main(){
           int i = -3;
           long l = 34567;
           char c = 'a';
           float f = 3.1466666666;
           double d = 3.1466666666;
           char arr[] = "小志的二逼精神永存";
           printf("%c
    ", c);
           printf("%d
    ", i);
           printf("%f
    ", f);
           printf("%lf
    ", d);
           printf("%u
    ", i);
           printf("%#x
    ", l);
           printf("%#o
    ", l);
           printf("%s
    ", arr);
           system("pause"); 
    }

     * 输入函数

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           printf("请输入班级人数:
    ");
           int number;
           //&:取出number的内存地址 
           scanf("%d", &number);
           
           printf("请输入班级名称:
    ");
           char name[10];
           scanf("%s", &name);
          
           printf("number的地址%#x
    ", &number);
           printf("name的地址%#x
    ", &name);
           printf("班级人数为%d,名称为%s
    ", number, name); 
           system("pause"); 
    }

     “*”的三种用法

    1. 乘法
    2. int* p:定义一个指针变量p,p中存放一个内存地址,这个地址所存放的数据规定是int型
    3. *p:取出p中保存的内存地址存放的数据

    * 指针和指针变量的关系

      指针就是地址,地址就是指针

      地址就是内存单元的编号

      指针变量是存放地址的变量

      指针和指针变量是两个不同的概念

      但是要注意: 通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样

    * 为什么使用指针

      指针的重要性

      直接访问硬件 (opengl 显卡绘图)

      快速传递数据(指针表示地址)

      返回一个以上的值(返回一个数组或者结构体的指针)

      表示复杂的数据结构(结构体)

      方便处理字符串

      指针有助于理解面向对象

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           int i = 3;
           //定义一个保存int类型数据的地址的指针变量 ,该变量的值是一个内存地址 
           int* p = &i;
           int** q = &p;
          
           printf("i的地址%#x
    ", p);
           
           printf("i的值为%d
    ", *p);
           printf("i的值为%d
    ", **q);
           system("pause"); 
    }
    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           //野指针:没有赋值的指针 
           int* p;
           int i;
           double d = 3.14;
           p = &d; 
           //*p = 23;
           printf("%#x
    ", p);
           printf("%lf
    ", *p);
           system("pause"); 
    }

    * 值交换(值传递: 所有语言所有平台,都只有值传递,引用传递传递的值是内存地址

    #include <stdio.h>
    #include <stdlib.h>
    void swap(int* p, int* q){
         int temp = *p;
         *p = *q;
         *q = temp;
    }
    main(){
           int i = 3;
           int j = 5;
           printf("i=%d
    ", i);
           printf("j=%d
    ", j);
           swap(&i, &j);
           printf("i=%d
    ", i);
           printf("j=%d
    ", j);
           system("pause"); 
    }

    * 主函数取子函数的值

    #include <stdio.h>
    #include <stdlib.h>
    void function(int** p){
         int i = 3;
         printf("i的地址为%#x
    ", &i);
         *p = &i;
    }
    main(){
           int* mainp;
           function(&mainp);
           printf("主函数中获取i的地址为%#x
    ", mainp);
           
           //子函数执行完后,里面的局部变量就会销毁
           //数据幻影 (如果上面两个打印被注释掉,那么在i的值被销毁之前,还是利用那么0.几秒的时候打印出来)
           printf("主函数中获取i的值为%d
    ", *mainp);
           system("pause"); 
    }

     

    * 数组入门

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
        //数组的内存地址是连续的,但要注意不同数据类型所占的字节是不一样的。
        //整个数组的内存地址就是第一个元素的内存地址,
       //char arr[] = "hello"; 
       int arr[] = {1,2,3,4,5};
       
       printf("%#x
    ", &arr[0]);
       printf("%#x
    ", &arr[1]);
       printf("%#x
    ", &arr[2]);
       printf("%#x
    ", &arr[3]);
       
       printf("数组名字的地址%#x
    ", &arr);
       
       //char* p = &arr;
       int* p = &arr;
       //+1表示向右偏移一个单位 
       printf("%d
    ", *(p+0));
       printf("%d
    ", *(p+1));
       printf("%d
    ", *(p+2));
       printf("%d
    ", (p+2)-p); 
       system("pause"); 
    }

     

    * 指针长度

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           char* cp;
           int* ip;
           short* lizhip;
           int i;
           char c;
           cp = &c;
           ip = &i;
           //指针的长度都是4个字节 
           printf("%d
    ", sizeof(cp));
           printf("%d
    ", sizeof(ip));
           printf("%d
    ", sizeof(lizhip));
           printf("%d
    ", cp-ip);
           system("pause"); 
    }

     

    * 堆 栈

    ##栈
    * 系统自动分配和释放
    * 保存全局、静态、局部变量
    * 在栈上分配内存叫静态分配
    * 大小一般是固定的
    ##堆
    * 程序员手动分配(malloc/new)和释放(free/java不用手动释放)
    * 在堆上分配内存叫动态分配
    * 一般硬件内存有多大就有多大

    堆和栈的区别:
    1.申请方式
    栈:   
    由系统自动分配.例如,声明一个局部变量int  b; 系统自动在栈中为b开辟空间.例如当在调用涵数时,需要保存的变量,最明显的是在递归调用时,要系统自动分配一个栈的空间,后进先出的,而后又由系统释放这个空间. 
    堆:   
    需要程序员自己申请,并指明大小,在c中用malloc函数   
    如char* p1  =  (char*) malloc(10);   //14byte
    但是注意p1本身是在栈中的.
      2  申请后系统的响应   
     栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。   
    堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,    会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。   
     
    3.申请大小的限制   
    栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(vc编译选项中可以设置,其实就是一个STACK参数,缺省2M),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。   
    堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。   
     
     4.申请效率的比较:   
    栈:由系统自动分配,速度较快。但程序员是无法控制的。   
    堆:由malloc/new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.   
     
     5.堆和栈中的存储内容   
    栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。   
    当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。   
    堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。   
     
    6.内存的回收
    栈上分配的内存,编译器会自动收回;堆上分配的内存,要通过free来显式地收回,否则会造成内存泄漏。
      堆和栈的区别可以用如下的比喻来看出:   
    使用栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。   
    使用堆就像是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

    * 栈上分配的就是静态内存,堆上分配的就是动态内存

    学号管理系统

    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    main(){
           printf("请输入学生人数:");
           int count;
           scanf("%d", &count);
           
           //根据学生人数去动态申请堆内存 
           int* p = malloc(sizeof(int) * count);
           
           int i;
           for(i = 0; i < count; i++){
                 printf("请输入第%d个学生学号:", i);
                 scanf("%d", p+i);
           }
           
           printf("请输入新增的学生人数:");
           int newCount;
           scanf("%d", &newCount);
           p = realloc(p, sizeof(int) * (count + newCount));
           
           for(i = count; i < count + newCount; i++){
                 printf("请输入第%d个学生学号:", i);
                 scanf("%d", p+i);
           }
           
           for(i = 0; i < count + newCount; i++){
                printf("第%d个学生的学号是:%d
    ", i, *(p+i)); 
           }
           system("pause"); 
    }

     

    * 多级指针

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           int i = 3;
           int* p = &i;
           int** q = &p;
           int*** l = &q;
           
           printf("i的值为%d
    ", ***l);
           system("pause"); 
    }

     

    * 结构体(长度会自动补齐)

    #include <stdio.h>
    #include <stdlib.h>
    void study(){
         printf("吃饭睡觉打李志
    ");
    }
    //定义一个结构体 
    struct student{
           int age;
           int height;
           char sex;
           
           //结构体中不能定义函数,但可以定义函数指针
           void (*studyP)(); 
    }
    
    main(){
           //定义结构体的变量 
           struct student st = {20, 180, 'm', study};
           printf("%d
    ", st.age);
           printf("结构体的长度%d
    ", sizeof(st));
           
           //调用函数指针有三种写法 
           st.studyP();
           
           struct student* stp = &st;
           (*stp).studyP();
           
           stp->studyP();
           system("pause"); 
    }

     

    * 联合体(长度取最大的那个)

    #include <stdio.h>
    #include <stdlib.h>
    
    main(){
           //定义一个联合体 
           union{long long i; short s; char c} un;
           un.i = 3;
           printf("%d
    ", un.i);
           printf("联合体的长度%d
    ", sizeof(un));
           system("pause"); 
    }

     

    * 枚举

    #include <stdio.h>
    
    enum WeekDay
    {
    Monday = 10,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
    };
    
    int main(void)
    {
      //int day;
      enum WeekDay day = Sunday;
      printf("%d
    ",day);
      system("pause");
      return 0;
    }

     

    * 自定义类型

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int haha;
    main(){
           haha i = 3;
           printf("%d
    ", i);
           system("pause"); 
    }

     

    NDKplatformsandroid-19arch-armuserincludejni.h中有C语言和JAVA语言之间的翻译

  • 相关阅读:
    ASP.NET Core WebAPI学习-4
    PIESDKDoNet二次开发配置注意事项
    PIE SDK影像快速拼接
    PIE SDK加载WMS服务数据
    PIE SDK加载自定义服务数据
    PIE SDK 距离分类和最大似然分类
    PIE SDK矢量点生成等值线、面
    PIE SDK与OpenCV结合说明文档
    C#录制声卡声音喇叭声音音箱声音
    C#录制屏幕采集系统桌面画面
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/5571624.html
Copyright © 2020-2023  润新知