[ndk,1]ndk开发,C语言入门讲解

浏览:
字体:
发布时间:2013-12-23 12:22:30
来源:东方联盟

一、C语言helloworld案例入门:

 

#include //引入头文件(引入函数库)相当于java import的操作

#include

main() //主函数,跟java类似 程序的入口函数

{

printf("Hello world !/n"); //在控制台输出

system("java cn.itcast.demo.HelloWorld");//调用执行java文件

system("pause");

}

 

//system("pause");是:调用cmd里面的暂停命令,让cmd窗口暂停执行以下 ,方便我们观察程序的执行结果.

 

二、C语言的基本数据类型:

c语言的数据类型

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

 

1.在c99的语法的中 是没有boolean的数据类型的,true false 非0代表真 0代表的是假.

2.c语言里面没有byte类型 ,

如何让c语言表示 java中的byte呢? 可以利用char类型代替java中的byte类型

 

3.c语言里面没有String的字符串 , c想表示一个字符串 一般是通过char数组来表示的

sizeof(); 参数是数据类型 返回值就是这个数据类型在内存中占用多少空间

4. 注意: signed, unsigned:只能修饰整数类型的数据 不能修饰浮点型的数据。

signed表示有符号,unsigned表示无符号。

 

5.java中的char是两个字节 ,c语言里面 1个字节

*/

#include //引入头文件 java import的操作

main()

{ // %d 代表的是一个占位符

printf("char占用的字节为%d/n",sizeof(char)); 1个字节

printf("int占用的字节为%d/n",sizeof(int)); 4个字节

printf("float占用的字节为%d/n",sizeof(float)); 4个字节

printf("double占用的字节为%d/n",sizeof(double)); 8个字节

printf("short占用的字节为%d/n",sizeof(short)); 2个字节

 

printf("long占用的字节为%d/n",sizeof(long));

printf("signed int占用的字节为%d/n",sizeof(signedint));

printf("unsigned int占用的字节为%d/n",sizeof(unsignedint));

 

//printf("unsigneddouble占用的字节为%d/n",sizeof(unsigned double)); 该行代码会报错。

system("pause");

 

}

三、输入输出函数:

1、C语言中的删除操作使用占位符实现的,不同类型的数据对应不同占位符:

%d - int

%ld – long int

%c - char

%f - float

%lf – double

%x – 十六进制输出 int 或者long int 或者short int

%o - 八进制输出

%s – 字符串

%hd - short

short

 

2、C语言的输入函数:

Int len;

Scanf(“%d”,&len); //扫描键盘的输入函数:

参数1:输入数据的指定类型的占位符。

餐宿2:指定保存输入数值的变量地址。

 

例:

#include //引入头文件 java import的操作

main()

{

int i = 129024;

long l = 333L;

char c ='B';

float f = 3.1415926f;

double d = 3.1415;

short s = 257;

 

printf("int i =%d/n",i);

printf("int l =%ld/n",l);

printf("int c =%d/n",c);

printf("int f =%f/n",f);

printf("int d =%lf/n",d);

printf("short s=%hd/n",s);

 

char cc;

printf("请输入一个int类型的值/n");

//& 取地址

scanf("%c",&cc);

printf("char cc =%c/n",cc);

//接收输入的字符串:使用char数组:

//定义一个char类型的数组 叫arr 用来存放字符串

char arr[]={' ', ' ',' ','',' '};

printf("请输入一个字符串/n");

scanf("%s",arr);

printf("数组的内容%s/n",arr);

system("pause");

 

}

 

四、指针:

1、所谓指针就是一个地址,地址其实就是一个内存空间的编号.

2、每个变量在内存中都有一个地址 :通过& 符号获取变量的地址.

例:

#include

main(){

int i;

//把i变量在内存中的地址 打印出来

 

//打印出变量的地址,指针就是一个地址 ,

//地址为十六进制:如:0xXXXX ,#表示打印的数值前面带0x

printf("i的地址为%#x/n",&i);

 

//60秒的倒计时

for(i =60; i>0;){

 

printf("剩余时间%d/n",i);

sleep(4000);

 

i--;

}

 

printf("游戏结束/n");

system("pause");

}

3、指针和指针变量:

例:

#include

main(){

// 1. 指针就是地址, 通过一个地址可以访问到一块内存空间, 如果修改这个内存空间里面的内容

 

int i = 5; //定义一个int类型的变量 变量的名字 叫 i 里面存放的内容 是一个int类型的值

// 2. 指针变量 用来存放一个变量地址的变量

int* p; //定义了一个int* 类型的变量 变量的名字叫p 里面存放的内容 是一个

//int* 类型的值

//也可以定义为:int *p; 或 int * p;

 

p = &i; // p里面存放的就是 i变量的地址了.

 

printf("p的值为%#x/n",p);

// 指针和指针变量的关系

// 指针是一个地址 ..

// 指针变量是存放一个地址的变量

//其实是两个完全不同的概念,但是 世面的书籍 习惯上把指针跟指针变量没有做区别

 

// * 号操作符的使用:

 

1.使用场景,定义一个指针变量 int* double* long*

2.表示两个数据相乘 3*5 = 15;

3. 如果*号后面跟的是一个指针变量, 用*可以访问指针变量内部存放的地址 里面存储的变量

 

 

//*p; //获取p变量里面存放地址所指向的变量,就是i对应的值;

//*p 和 i 代表的是同一个变量

printf("*p的值为%d/n",*p);

system("pause");

}

 

五、指针的常见错误:

1、指针未经赋值不能使用: 以下代码会报错:

#include

main(){

int i = 5;

int* p ;

printf("*p的值为%d/n",*p);

system("pause");

}

2、不同的指针类型 不能进行相互的转化

#include

/**

不同的指针类型 不能进行相互的转化

每一种变量类型 在内存中占用的空间 是不相同的.

*/

 

main(){

short s = 278;

 

int i = 2777777; //4个byte

 

int* p = &i;

short* q = &i; // short 在内存空间里面占用的是两个 byte

 

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

printf("*q=%hd/n",*q);

 

 

 

system("pause");

}

3、不能使用已经被系统回收掉的内存空间里的数据:

 

 

 

六、案例:交换两个数字.

通过修改地址里面的值 达到了交换数据的目的

 

#include

void swap2(int* p, int* q){//p代表的是 i的地址, q代表的是 j的地址

 

// 把i变量和 j变量的地址 传递给了子函数,在子函数里面直接通过修改地址里面的值 达到了交换数据的目的

// *p 代表的就是 i变量

 

// *q 代表的就是 j变量

 

int temp;

temp = *p;

*p = *q;

*q = temp;

 

 

}

//主方法

main(){

int i = 3;

int j = 5;

// swap(i,j);

 

swap2(&i,&j);

printf("i=%d/n",i);

printf("j=%d/n",j);

 

system("pause");

}

 

七、指针的作用:

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

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

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

 

例:在子函数中同时修改两个变量对应的值:

#include

 

//相当于是让子函数 修改了主函数里面连个数据的值, 子函数返回一个以上的数据

void f(int* p , int* q){ // p表示的是i的地址, q代表的是 j的地址

*p = *p+3;

*q = *q+3;

 

}

main(){

 

int i = 3;

int j = 5;

f(&i,&j); //调用子函数

printf("i=%d/n",i);

printf("j=%d/n",j);

 

system("pause");

}

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

5、 方便处理字符串

// c语言是没有String类型的 要在c语言里面表示一个字符串 一般都是通过字符数组的方式表示

 

#include

main(){

// char arr[]={'h','e','l','l','o'};

 

//char类型的指针变量

char* arr ="hello";

//输出字符传

printf("%s/n",&arr[0]);//arr[0]字符数组的首地址。

 

system("pause");

}

 

6 、指针有助于理解面向对象

 

八、指针和数组之间的关系:

1、数组:

数组在内存中是一块连续的内存空间。

数组的名称 等于数组中第一个元素的地址(首地址)。

int arr[]={1,2,3,4};

 

printf("arr = %#x /n",arr);

printf("第一个元素的地址为%#x/n",&arr[0]);

上面两行代码输出的值相同。

2、指针操作数组:

 

例:开发一个子方法 把数组的每一个元素都打印出来

#include

 

// 第一个参数 数组的首地址, 第二个参数 数组的长度

void printArr(int* parr , intlen){

int i;

for( i=0;i

//输出方式一:根据数组的下标获取数组中的值:

printf("arr[%d]=%d/n",i,parr[i]);

 

// *parr //数组第一个元素对应的内容

//*(parr+1) 获取数组第二元素对应的内容(因为内存是连续的空间)

printf("arr[%d]=%d/n",i,*(parr+i));

}

}

 

main(){

int arr[]={1,2,3,4,5,6,7,8,9};

printArr(arr,9);

system("pause");

}

九、指针的运算:

1、指针的运算只对连续的内存空间才有意义,数组是一块连续的内存空间:

例:数组元素指针之间的运算:

#include

main(){

 

//数组是一块连续的内存空间

int intarr[] = {1,2,3,4,5,6,7,8,9};

// int* arr0 = &intarr[0];

 

int* arr0 = intarr;//数组第一个元素的地址

 

int* arr1 = &intarr[1];

 

int* arr2 = &intarr[2];

 

printf("arr0地址为%#x/n",arr0);

printf("arr1地址为%#x/n",arr1);

printf("arr2地址为%#x/n",arr2);

 

 

printf("arr2与arr0之间的距离为%d/n", arr2 - arr0);

// 指针的运算 相减和相加得到的结果其实都是 内存地址的偏移量,不是单纯的内存地址整数加减结果.结果代表的有特殊的业务含义, 几个内存空间之间的偏移量.

 

char chararr[] ={'1','2','3','4','5'};

// int* arr0 = &intarr[0];

 

char* chararr0 = chararr;//数组第一个元素的地址

 

char* chararr1 = &chararr[1];

 

char* chararr2 = &chararr[2];

 

printf("chararr0地址为%#x/n",chararr0);

printf("chararr1地址为%#x/n",chararr1);

printf("chararr2地址为%#x/n",chararr2);

 

 

printf("chararr2与chararr0之间的距离为%d/n", chararr2 - chararr0);

 

system("pause");

}

九、指针的长度:

#include

main(){

//在32位的操作系统上, 2的32次方个内存地址 4个byte

// 在我当前的32电脑操作系统上 用的devcpp工具, gcc

 

 

int i =3;

int* ip = &i;

 

double d = 3.14159;

double* dp = &d;

 

 

float f = 6.28f;

float* fp = &f;

 

 

short s = 255;

short* sp = &s;

 

//指针的长度都为4。

printf("int的指针长度为%d/n", sizeof(ip));

 

 

printf("double的指针长度为%d/n",sizeof(dp));

 

 

printf("float的指针长度为%d/n",sizeof(fp));

 

 

printf("short的指针长度为%d/n",sizeof(sp));

 

 

 

system("pause");

}

 

十、动态内存和静态内存:

1、动态内存

动态内存创建在堆空间上的 一块不连续的内存空间 可以占用整个操作系统的全部内存

堆内存就是操作系统维护的剩余的内存空间,

在java里面new出来的的所有的对象都是分配在堆内存里面。

在C语言里面,申请堆内存空间使用malloc 函数。

malloc函数接受一个参数 ,参数代表动态的在堆内存申请多大的内存空间.

malloc的返回值 代表的是申请的这块内存空间的首地址.

使用free(intp);函数释放堆内存空间,将堆内存标记为可用。

 

 

例:申请堆内存空间:

 

#include

//引入动态内存分配的头文件

#include

 

f(int** padress){

 

//*padress 拿到了主函数里面的p变量

 

// 申请一块内存空间 空间的大小为8个字节,空间的首地址把他赋给 intp的变量

int* intp = (int*)malloc(sizeof(int)*2);

 

 

*intp = 33; // 在堆内存申请的空间里面放置一个int类型的值 值为33

*(intp+1) = 99; //

 

*padress = intp; //把堆内存的地址赋给 主函数里面的p变量

//free(intp); //释放堆内存空间,将堆内存标记为可用。

printf("子函数i的地址为%#X/n",intp);

 

}

main(){

 

int* p ;// 用来存放 子函数里面的i变量的地址

 

//int -> int* ->int**

 

//在主函数里面把子函数的i变量的地址给获取出来

f(&p);

// 手动的回收掉申请的那块内存空间

free(p); // 99 内存中的残留的影像,或者幻影

 

printf("主函数i的地址%#X/n",p);

printf("主函数 i的值为%d/n",*p);

printf("主函数 第二个的值为%d/n",*(p+1));

system("pause");

}

 

2、静态内存 创建在栈空间上的 一块连续的内存空间 2M

3、动态内存优点:

动态内存可以跨函数使用,静态函数不可以。

动态内存中数组的长度能在函数运行中动态增加或者缩小

动态的增加数组长度:使用reallco函数。

 

例:动态的增加数组长度:使用reallco函数:

#include

//引入动态内存分配的头文件

#include

 

void printArr(int* arr , intlen){

int i;

for(i = 0; i

printf("学生编号%d的成绩为%d/n",i,arr[i]);

}

}

main(){

 

printf("请输入学生的总数/n");

int len;

scanf("%d",&len);

 

//根据len动态的创建一个数组

 

int* pgrade = malloc(sizeof(int)*len);

 

int i;

for(i=0;i

printf("请输入学生%d的成绩/n",i);

scanf("%d",(pgrade+i));

}

 

printf("打印学生的成绩列表/n");

 

printArr(pgrade,len);

 

 

printf("请输入增加学生的个数/n");

int addnumber;

scanf("%d",&addnumber);

 

pgrade = realloc(pgrade,sizeof(int)*(len+addnumber));

int j;

for(j=len;j<(len+addnumber);j++){

printf("请输入新添加的学生%d的成绩/n",j);

scanf("%d",(pgrade+j));

}

printf("重新打印学生的成绩列表/n");

 

printArr(pgrade,len+addnumber);

system("pause");

}

 

十一、堆和栈的区别:

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.堆和栈中的存储内容

栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。

当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

 

6.内存的回收

栈上分配的内存,编译器会自动收回;堆上分配的内存,要通过free来显式地收回,否则会造成内存泄漏。

堆和栈的区别可以用如下的比喻来看出:

使用栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

使用堆就像是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

 

十二、java的值传递和引用传递:

public StringgetPersonName(Person p){

return person.getName();

}

 

p变量里面存放的是一个 堆内存里面person对象的地址. (值). // 感觉java是只有值传递。

 

p变量他代表的是person对象的一个引用, 引用传递.

 

十三、多级指针:

例:使用r取到i的值:

#include

 

main(){

 

int i = 3;

int* p = &i;

 

int** q = &p;

 

 

int*** r = &q;

 

//取到i 的值

printf("i=%d/n",***r);

 

 

 

system("pause");

}

十三、函数的指针:

获取函数的首地址,通过首地址,就可执行该函数。

 

例:

#include

/**

1.定义int (*pf)(int x, int y);

2.赋值 pf = add;

3.引用 pf(3,5);

*/

 

int add(int x, int y){

 

return x+y;

}

 

main(){

int (*pf)(int x,int y); // 定义一个函数的指针指针的类型是返回值为int 接受的参数 int

pf =add;

printf("result=%d/n", pf(3,6));

system("pause");

}

 

十四、结构体:使用struct 定义结构体:

 

#include

//定义一个结构体

struct Student

{

char sex; //1

int age; //4

float score; //4

int id; //4

};

 

main(){

//

struct Student st={80,55.6f,10000,'F' };

 

//获取结构体的指针

struct Student* pst = &st;

 

printf("age=%d/n",st.age);

 

//结构体的长度

printf("结构体的长度%d/n",sizeof(st));

 

//通过指针获取结构体中的变量

printf("age=%d/n", (*pst).age);

//通过指针获取结构体中的变量 的第二种写法:

printf("age=%d/n", pst->age);

system("pause");

}

 

十四、联合体:

// 联合体的作用是声明一块公用的内存空间,长度跟公用的数据类型中最长的一个条目一致,

当多次为同一个联合体赋值时,会覆盖:

 

 

#include

 

main( )

{

 

struct date { int year, month, day;}today;

union { long i; int k; char ii; } mix;

 

// 联合体的作用是声明一块公用的内存空间

// 长度跟公用的数据类型中最长的一个条目一致

printf("date:%d/n",sizeof(struct date));

 

printf("mix:%d/n",sizeof(mix));

//下面的赋值,先定义的会被覆盖。

mix.i = 99;

mix.k = 18;

mix.ii = 'A';

printf("i=%ld",mix.i);

 

system("pause");

}

十五、枚举:

#include

enum WeekDay

{

Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday

};

 

int main(void)

{

//int day;

enum WeekDay day = Sunday;

printf("%d/n",day);

 

system("pause");

}

 

十六、typedef:

声明自定义数据类型,配合各种原有数据类型来达到简化编程的目的的类型定义关键字。

typedef int haha;//声明一个int型的数据类型

 

例:

#include

typedef int haha;

int main(void)

{

haha i = 3;

printf("%d/n",i);

 

system("pause");

 

return 0;

}

 

>更多相关文章
24小时热门资讯
24小时回复排行
资讯 | QQ | 安全 | 编程 | 数据库 | 系统 | 网络 | 考试 | 站长 | 下载 | 关于东盟 | 安全雇佣 | 搞笑视频大全 | 微信学院 |
关于我们 | 联系我们 | 广告服务 | 人才招聘 | 服务条款 | 免责申明 | 帮助中心 | 作品发布 | 网站地图 | 技术培训
Copyright © 2007 - 2018 Vm888.Com. All Rights Reserved
东方联盟 版权所有