zoukankan      html  css  js  c++  java
  • 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语言之间的翻译

  • 相关阅读:
    Spring Boot (20) 拦截器
    Spring Boot (19) servlet、filter、listener
    Spring Boot (18) @Async异步
    Spring Boot (17) 发送邮件
    Spring Boot (16) logback和access日志
    Spring Boot (15) pom.xml设置
    Spring Boot (14) 数据源配置原理
    Spring Boot (13) druid监控
    Spring boot (12) tomcat jdbc连接池
    Spring Boot (11) mybatis 关联映射
  • 原文地址:https://www.cnblogs.com/anni-qianqian/p/5571624.html
Copyright © 2011-2022 走看看