C语法

JNI的概念

Java Native Interface java本地接口
Native Native Language 本地语言 看操作系统使用什么语言开发的 那么这个语言就是本地语言
java c/c++ 通信的接口

Java 特点 一处编译到处运行 通过java虚拟机 把java代码和底层的操作系统隔离起来
c/c++ 平台相关性强

① java 想与硬件之间直接交互 不能直接交互 需要访问硬件的驱动 java需要调用C的代码
② java 运行的速度 比c要慢一些 高清视频回放 视频解码的库都是用c/c++去开发的
③ java 编译之后生成.class .class可以很容易的进行反编译 c编译之后生成机器码 机器码只能反汇编
金融软件
④ c语言有好多开源库 openCV ffmpeg vitamio

学习的目的 ①可以看懂android 所有的源码
② 有一些特定的需求 需要通过调用C去实现 需要使用JNI

Native c语言的基础 能看懂会调用
Interface NDK native develop kit
Java->C
c-> java
实际案例

c helloworld

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
​
main(){ //c 程序的入口  和 java 的 public static void main(String args[]) 
    printf("hello world!\n"); // System.out.print  向控制台输出一句话 
    system("pause");           //system 调用当前平台的指令 
    system("calc"); 
}

c 基本数据类型
java的基本数据类型 C的基本数据类型
boolean 没有boolean 0 false 非0 true
byte 没有byte
char 2 char 1
short 2 short
int 4 int
long 8 long 4
float 4 float
double 8 double

signed和unsigned 可以用来修饰整形变量 short int long char
signed 有符号 默认情况下都是有符号的
unsigned 无符号 使用了unsigned 来修饰整形变量 这个整形变量的最高位就是数值位 不再是符号位

C 输出函数
00000000 10111100 01100001 01001110
01100001 01001110
使用占位符的时候 一定要注意 类型和占位符之间一定要一一对应 如果用错了可能会出现问题

C 数组的声明 [] 一定要放到变量名字的后面
char str[]

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
/**
%d  -  int
%ld – long int
%lld - long long
%hd – 短整型  short
%c  - char
%f -  float
%lf – double
%u – 无符号数
%x – 十六进制输出 int 或者long int 或者short int
%o -  八进制输出
%s – 字符串
​
​
*/
​
main(){ 
    char c = 'a';
    short s = 1234;
    int i = 12345678;
    long l = 1234567890;
    float f = 3.14;
    double d = 3.1415926;

    printf("c = %c\n",c);
        printf("s = %hd\n",s);
            printf("i = %d\n",i);
                printf("l = %ld\n",l);
                    printf("f = %.2f\n",f);   //输出小数的时候默认显示6位有效数字  控制有效数字的位数 %.xf  %.xlf  
                        printf("d = %.7lf\n",d);
    printf("i = %#x\n",i);
    printf("i = %#o\n",i); // %#x  %#o 带前缀输出8进制数 和16进制数

    //java 字符串 string    c的字符串实际上就是字符的数组  字符数组结束的标记就是 '\0'   

    char str[] = {'a','b','c','d','e','\0'};
    char str1[] ="你好"; 
    printf("str = %s\n",str1);

    system("pause");    
}

C 输入函数

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
​
main(){ 
    int count;
    printf("请输入班级的人数:");
    scanf("%d",&count);  //& 取地址符  把 count这个变量的地址取出来   用户的输入会保存到count变量中
    printf("班级的人数为:%d\n",count); 
    printf("count的地址:%d\n",&count); 
    char name[2];
    printf("name的地址:%d\n",&name); 
    printf("请输入班级的名字:");
    scanf("%s",&name);                     
    printf("班级的人数是:%d\n班级的名字是:%s\n",count,name);             //C数组不检查越界 
    system("pause");    
}

内存地址的概念
内存的最小单位 byte 8位二进制数
内存要使用的时候 一定得对每一个byte进行编号 只有编号之后才能使用
32位系统 xp /win7 地址线32位 4G的内存
64位系统

C 的指针 ☆☆☆☆☆

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
// 类型 * 变量名   pointer  
main(){ 
    int i = 456;    // 这一行执行之后 会在内存中给变量i分配一块内存空间 这块内存的地址就是 0X24fe44 
    int* p = &i;
    printf("p = %#x\n",p);
    printf("i的地址%#x\n",&i); 

    printf("*p = %d\n",*p); 

    *p=789;
    printf("i = %d\n",i); 
    system("pause");    
}

int i = 123; int* p = &i;
p *p &p

C指针的常见错误

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
//要避免野指针  在使用指针变量做赋值操作之前, 用自己程序中的变量的地址为指针变量赋初始值 
//指针变量的类型要对应起来 int类型的变量地址 通过int类型的指针变量保存  double类型的变量地址 通过double类型的指针变量保存 
​
main(){ 
    int i; 
    int* p = &i;  //野指针  指针变量声明之后没有赋初始值 直接对这个指针指向的地址做赋值的操作  
    printf("p = %#x\n",p);
    *p = 1234;


    double* p2 = &i;
    printf("*p2 = %lf", *p2);
    system("pause");    
}

C 指针的练习
交换两个数的值
值传递 调用函数/方法的时候 传到方法中的是变量的值 值传递
引用传递 调用函数/方法的时候 传到方法中的也是数值 只不过这个值是一个地址值 引用传递
交换两个数

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
void swap(int i, int j){
    int temp = i;
    i = j;
    j = temp;
}
​
void swap2(int* p, int* p2){
    int temp = *p;
    *p = *p2;
    *p2 = temp;
}
​
main(){ 
    int i = 123;
    int j = 456;

//  int temp = i;
//  i = j;
//  j = temp;
//  swap(i,j);
    swap2(&i,&j);

    printf("i = %d,j= %d\n",i,j);
    system("pause");    
}

返回多个值

 void function(int* p, int* q){
    *p *= 2;
    *q *= 2;
 }
main(){ 
    int i = 123;
    int j = 456;

    function(&i,&j);
    printf("i = %d,j = %d\n",i,j);

    system("pause");    
}

C 数组 和指针之间的关系
java的数组 是一块连续的内存空间

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
// 表示地址的时候一般用十六进制来表示 
main(){ 
//  char array[] = {'a','b','c','d','e'};
    int array[] = {1,2,3,4,15};
    printf("array[0]的地址%#x\n",&array[0]);
    printf("array[1]的地址%#x\n",&array[1]);
    printf("array[2]的地址%#x\n",&array[2]);
    printf("array[3]的地址%#x\n",&array[3]);
    printf("array[4]的地址%#x\n",&array[4]);

//  char* p= &array[0];
   printf("array的地址%#x\n",&array);//数组的名字的地址 实际就是第一个元素的地址 也就是这个数组的首地址
//   char* p = &array; 
   double* p = &array;
//   printf("array[0] = %c\n",*(p+0));
//   printf("array[1] = %c\n",*(p+1));
//   printf("array[2] = %c\n",*(p+2));
//   printf("array[3] = %c\n",*(p+3));
//   printf("array[4] = %c\n",*(p+4));
    printf("array[0] = %d\n",*(p+0));
   printf("array[1] = %d\n",*(p+1));
   printf("array[2] = %d\n",*(p+2));
   printf("array[3] = %d\n",*(p+3));
   printf("array[4] = %d\n",*(p+4));

   printf("p+0= %#x\n",p+0);
    printf("p+1= %#x\n",p+1);
     printf("p+2= %#x\n",p+2);
      printf("p+3= %#x\n",p+3);
       printf("p+4= %#x\n",p+4);
    //数组的首地址   也就是第一个元素的地址 也是数组变量名字获取的地址
    //获取到数组的首地址之后 可以通过指针变量 遍历整个数组
    //指针的位移运算    给指针 p+1 p+2  指针的位移运算 指针变量每+1 移动的字节数跟指针变量的类型有关
    // int 类型指针 p+1 会移动4个字节  char* p  p+1之后 移动1个字节  shortr* p  p+1之后 移动2个字节  double* p  p+1之后 移动8个字节 
    system("pause");    
}

C的字符串的最常用的声明方式

#include <stdlib.h>   // include 包含 类似java 的import  
#include <stdio.h>   // .h head C的头文件   std standard 标准的   stdlib 标准函数库  stdio.h 标准输入输出流 
​
main(){ 
    char str[] = {'a','b','c','d','e','\0'}; // c字符串 char类型的数组 
    char str2[] ="abcde";
    //printf("str的值%#x\n",&str); 
    char* str3 = "你好";   // char*  类似于java的 string 
    printf("%s\n",str3);
    printf("%#x\n",str3);
    system("pause");    
}

C指针变量的长度

C 的多级指针
用2级指针保存1级指针的地址
用n级指针 保存 n-1级指针的地址

main(){ 
    int i = 123;
    int* p = &i;
    int** p2 = &p;
    int*** p3 = &p2;
    ***p3= 456;
    printf("i = %d\n",i);
    system("pause");    
}

main函数中 获取子函数临时变量的地址

void function(float** q){
    float i = 123.4;
    *q = &i;    
    printf("i的地址%#x\n",&i); 
}
main(){ 
    float* p;
    function(&p);
    printf("p = %#x\n",p); 
    system("pause");    
}

静态内存分配和动态内存分配
静态内存分配 栈内存 大小固定 高地址向低地址扩展 栈内存的分配和回收是系统控制

int* function1(){
    int array[] = {1,2,3,4,5};
    printf("array的地址%#x\n",array); 
    return &array;
}
​
int* function2(){
    int array2[] = {15,4,3,2,1};
    printf("array2的地址%#x\n",array2); 
    return &array2;
}
​
main(){ 
    int* p = function1();
    function2();
    printf("*(p+0)= %d,*(p+1)= %d,*(p+2)= %d,*(p+3)= %d,*(p+4)= %d\n",*(p+0),*(p+1),*(p+2),*(p+3),*(p+4));
    printf("*(p+0)= %d,*(p+1)= %d,*(p+2)= %d,*(p+3)= %d,*(p+4)= %d\n",*(p+0),*(p+1),*(p+2),*(p+3),*(p+4));
    system("pause");    
}

C 的结构体☆☆☆☆☆
C 的联合体
C 的枚举
C 的自定义类型

猜你喜欢

转载自blog.csdn.net/a94721990/article/details/81090503
今日推荐