Android之NDK开发(一)C语言初识

来源:互联网 发布:身份证识别器录入软件 编辑:程序博客网 时间:2024/06/16 09:15

一、基本数据类型

C的基本数据类型
char(1),int(4),short(2),long(4),float(4),double,signed,unsigned,and,void(1)
java的基本类型
char(2),int(4),short(2),long(8),float(4),double(8),byte(1),boolean (1)
注意标准的c99 没有:byte 和 boolean 类型
sizeof 属于运算符,不属于函数,获取变量或者数据类型所占用的字节数

二、输入输出函数

%d  -  int%ld – long int%c  - char%f -  float%u – 无符号数%hd – 短整型%lf – double%x – 十六进制输出 int 或者long int 或者short int%o -  八进制输出%s – 字符串printf("int i = %d\n",sizeof(i));scanf("%s", c);

三、指针

使用指针的优点

1.直接访问硬件 (opengl 显卡绘图)2.快速传递数据(指针表示地址)3.返回一个以上的值(返回一个数组或者结构体的指针)4.表示复杂的数据结构(结构体)5.方便处理字符串 6.指针有助于理解面向对象

变量和地址

1.变量的本质是系统分配变量的内存,内存大小由变量的数据类型决定2.内存都有内存地址,获取变量的内存地址则用&变量3.指针就是一个变量的内存地址4.指针本身就是一个内存的地址,我们可以将这些指针以变量的形式存储,即为指针变量5.指针变量的定义,数据类型 *变量(int *a),可以存放变量的地址(指针)例如:int i= 100int *p;p = &i;这里就将i的内存的地址存放于指针变量p中6.指针变量本身也有内存和地址7.指针变量可以得到所指向的变量的值,*p;

指针和指针变量的关系

1.指针就是地址,地址就是指针2.地址就是内存单元的编号3.指针变量是存放地址的变量4.指针和指针变量是两个不同的概念5.但是要注意: 通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样

四、数组与指针

1.数组是连续的内存块2.数组名师数组的首地址3.指向数组的指针加减的时候,按照数组元素所占有的内存大小的字节数去自增或自减4.定义的指针变量指向数组,这个指针变量可以通过数组的索引去取得数组的值5.数组的首地址虽然是指针,但并不是指针变量,不能自增自减

五、结构体

1.结构是由基本数据类型构成的、并用一个标识符来命名的各种变量的组合2.结构中可以使用不同的数据类型3.结构体指针变量(*)4.结构体也可以是一种数据类型        //定义结构体    struct Person{        int id;        char name[10];        //通常用char*表示一个字符串        char* address;        int age;    }    main(){        //定义结构体变量        struct Person person;        //通过结构体.成员变量调用;        person.id = 100;    }

结构体的特点

1.内存地址和第一个成员的地址一样2.占有的内存大小原则上就是所有的成员所占有的内存之和3.定义一个结构体的指针变量    struct Person *p = &person;4.一个指向结构体的指针变量通过箭头的形式去引用结构体包里面的成员变量    p->age = 21;    printf("id=%d,name=%s,age=%d\n",p->id,p->name,p->age);

六、函数指针
函数也占用内存, 一旦函数被编译载入计算机中执行,它就会占有一块内存。这块内存有一个地址,因此函数也有地址,可以通过指针使用函数,就像可以使用变量的地址一样。因此有地址就有指针,这里我们便引用一个指针变量取操作函数,即为函数指针,函数的地址就是函数的名字;

    int add(int a,int b){        return a+b;    }    //定义函数指针    int (*a)(int,int) = add;    //调用    (*a)(&1,&3);

七、栈和堆

静态内存是程序编译执行后系统自动分配, 由系统自动释放静态内存是栈分配的,而动态内存是堆分配的void function(){    //方法里面的变量是在栈空间由系统自动分配的,属于静态变量,有系统自动回收    int i = 100;    //由程序员手动创建内存块,用函数malloc在堆空间创建内存    int* i = malloc(4);    //这里如果没有手动回收,那么会内存泄漏,Java则有垃圾回收机制    //堆内存不能被系统是自动回收,需要我们手动去回收    free(i);}内存溢出:所分配的内存不足以存储当前所需的内存,导致溢出内存泄漏:这里如果在堆内存中没有主动回收,所占内存越来越多,导致内存不足,最终内存溢出

堆和栈的区别:

1.申请方式
栈: 由系统自动分配.例如,声明一个局部变量int b; 系统自动在栈中为b开辟空间.例如当在调用涵数时,需要保存的变量,最明显的是在递归调用时,要系统自动分配一个栈的空间,后进先出的,而后又由系统释放这个空间.

堆: 需要程序员自己申请,并指明大小,在c中用malloc函数 如char* p1 = (char *)malloc(10); 但是注意p1本身是在栈中的.

2 申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

3.申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(vc编译选项中可以设置,其实就是一个STACK参数,缺省2M),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

4.申请效率的比较:
栈:由系统自动分配,速度较快。但程序员是无法控制的。
堆:由malloc/new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.

5.内存的回收
栈上分配的内存,编译器会自动收回;
堆上分配的内存,要通过free来显式地收回,否则会造成内存泄漏。
堆和栈的区别可以用如下的比喻来看出:
使用栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就像是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

八、类型说明

类型说明只定义了一个数据类型的新名字,而不是定义一种新的数据类型;typedef同样可用来说明结构、联合以及枚举#typedef int I;#typedef struct{} Person;//结构体main(){    I(int数据类型的别名) i = 100;    //等同于 int i = 100;    Person person;} #define 指令 #define 指令是一个宏定义指令,定义的一般形式是: #define 宏替换名(或数值),在程序中每次遇到该红替换名时就用所定义的字符替换

九、文件

fopen("文件名","打开模式");//例如现在的文件Looper.javaFile* f1 = fopen("Looper.java","r");//r表示以读的形式打开一个文件,返回的是一个文件指针
//从流中读取一个字符int  c = fgetc(f1);//读取整个文件的数据while((c=fgetc(f1))!=-1){     printf("%c/n",c);}
//写整个文件的数据,添加写的权限File* f2 = fopen("Looper.java","w");while((c=fgetc(f1))!=-1){     printf("%c/n",c);     fputc(c,f2);}
//关闭文件fclose();
原创粉丝点击