您的位置:首页 > 其它

逆向技能+1

2016-07-06 23:55 239 查看

下面是技能表:



android看完第一行代码后,有过一定基础了。

就从NDk开发开始学习。

因为NDk开发需要JNI 所以把c的基础又看了一遍。

C语法基础

Helloworld

C的基本数据结构

输出函数

输入函数

内存地址的概念

指针

指针的联系

多级指针

指针和数组的关系

结构体

联合体 枚举 自定义类型

输出 helloworld

1.Target:pritnf–》 helloworld

2.open the Calculator

include

main(){ //public static void main(String args[]){}
printf("hello world!\n");
system("calc");
system("pause");//调用系统的命令 在这是调用windows的命令
}


C的基本数据类型

java的数据类型:四类八种 c的基本类型

boolean 1

byte 1

char 2 char 1*

short 2 short 2

int 4 int 4

long 8 long 4*

float 4 float 4

double 8 double 8

c没用boolean 而是用0和非零表示 false 和 true

java一个byte是8位二进制数

第一位是符号位 00010001

符号位为0 表示正数

符号位为1 表示负数

输出函数

c char

unsigned 只能用来修饰整形的变量 char short int long

11111111 0~255

singed 最高位是符号位 可以表示负数,但是表示的最大值相对要小

//关键字:sizeof(类型名字) sizeof 变量名

//printf 需要一个占位符

main(){ //public static void main(String args[]){}

printf(“int4类型占%d个字节\n”,sizeof(int));

printf(“char2%d个字节\n”,sizeof(char));

printf(“float4%d个字节\n”,sizeof(float));

printf(“double8%d个字节\n”,sizeof(double));

printf(“lon8g%d个字节\n”,sizeof(long));

printf(“short4%d个字节\n”,sizeof(short));

unsigned char c1=255;

char c2=255;

printf(“c1=%d\n”,c1);

printf(“c2 = %d\n”,c2);

system(“pause”);//调用系统的命令 在这是调用windows的命令

}

占位符的选用

占位符要与输出的数据类型相匹配 不然会出现精度问题

/*占位符

%d - int

%ld - long

%lld - long long

%hd - 短整型

%c –char

%f -float

%lf -double

%u -无符号位

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

%s -字符串

*/

//printf 需要一个占位符

main(){ //public static void main(String args[]){}

int a =10;

char b= ‘Z’;

long c=92890;

float f=1.34;

printf(“%d\n”,a);

printf(“%c\n”,b);

printf(“%ld\n”,c);

printf(“%.1f\n”,f);//控制输出小数的有效位数%.位数f/d

system(“pause”);//调用系统的命令 在这是调用windows的命令

}

数组的表示方法

main(){

char array[]={‘a’,’b’,’c’,’\0’};//array位数数组需要手动添加结束符’\0’结束符也会占用一个字节

//array里面不能直接打印中文

char arraya[]=”abc啊啊啊”;

printf(“array为%s\n”,array);

printf(“arraya为%s\n”,arraya);

system(“pause”);//调用系统的命令 在这是调用windows的命令

}

输入函数

接受用户在控制台输入

java 里面的system.in

c 里面获取用户输入的函数为scanf(“%d”,内存地址) &为取地址符 c里面取地址符不能越界 使用的时候请注意

//printf 需要一个占位符

main(){

printf(“请输入班级的人数\n”);

int count;

scanf(“%d”,&count);//&取地址符,通过&把count对应的内存地址取出来

printf(“班级的人数为:%d\n”,count);

char name[4];

printf(“count的内存的值为%d\n”,&count);

printf(“name的内存的值为%d\n”,&name);

printf(“请输入班的名字:\n”);

scanf(“%s”,&name);

printf(“班级的人数%d,和班级的名字%s\n”,count,name);

system(“pause”);//调用系统的命令 在这是调用windows的命令

}

内存地址的概念

计算机中一般习惯用16进制的整数表示内存地址

当生命一个变量 就会为这个变量在内存中申请一块内存空间

这个内存一定对应着一个编号,也就是内存地址的内存是没办法使用的

内存与cpu的关系?

答:

32位操作系统 地址总线32位 2^32次方 最大支持4个g

*为什么买来的内存是16g,而实际却没有16g?

显卡等其他硬件会占用系统的内存编号资源,而且还有就是按1000计算

*内存地址有什么用?

玩RPG游戏时如仙剑三,用修改器修改地址

Cheat Engine显示正在运行的内存,

还有金山游侠等修改器。

指针

main(){

int i=123;

printf(“i内存地址%#x \n”,&i);

//int*就是定义了类型的指针变量 用来保存int类型的变量的内存地址

//通过指针变量 可以和直接对内存地址保存的值 进行读写操作

//pointer pointer在等号右边 就是要读出它指向内存的值 *pointer在等号左边 就是要对它指向的内存的进行赋值的操作

int* pointer =&i;

printf(“pointer =%#x \n”,pointer);

//*pointer

printf(“*pointer==%d\n”,*pointer);

printf(“pointer =%#x \n”,&pointer);

system(“pause”);//调用系统的命令 在这是调用windows的命令

}

指针使用常见的错误

1.野指针,未初始化就直接通过指针进行赋值操作

初始化 就是把自己程序中的变量的内存地址 赋值给指针

2.指针类型也要匹配

int类型的指针变量只能用来保存 int类型变量的内存地址

c语言交换两个值的实现

void swap(int *p1, int *p2){

int tmp=*p1;

*p1=*p2;

*p2=tmp;

}

void main(){

int a=5;

int b=10;

//swap(i,j);引用传递

//值传递 传递的也是值,只不是传递的是变量的内存地址

swap(&a,&b);

printf(“%d\n”,a);

printf(“%d\n”,b);

}

C的优势是有指针 可以直接操作内存

在数据交换中有很大的优势

C中定义int 数组【】一定要在变量名之后

c语言看数组是否是连续的

//根据输出结果可得char的地址是连续的

static char(){

char array[]={‘a’,’b’,’c’,’d’,’\0’};

printf(“array的地址%d\n”,&array[0]);

printf(“array的地址%d\n”,&array[1]);

printf(“array的地址%d\n”,&array[2]);

printf(“array的地址%d\n”,&array[3]);

}

//int类型的数组地址不是连续的

void main(){

int a[]={1,2,23,4,4};

printf(“array的地址%x\n”,&a[0]);

printf(“array的地址%x\n”,&a[1]);

printf(“array的地址%x\n”,&a[2]);

printf(“array的地址%x\n”,&a[3]);

printf(“array的地址%x\n”,&a);

}

指针类型要匹配数据类型

c中字符串和数组类似

char *str=”abcd”

char array[]={‘a’,’b’,’c’,’d’,’\0’};

char *str=&array[];

多级指针

int i=23;

//一级指针

int*p=&i;

//二级指针

int**p1=&p;

//不能这样定义二级指针

int*q=&p;

error:cannot convert int** to int *;

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

//这段程序的实质是把int变量i的地址给p1;

void function(int** p){

int i=200;

*p=&i;

printf(“%d\n”,&i);

//打印变量i的地址

printf(“&i=%d\n”,p);

}

//多级指针

void main(){

int *p1;

function(&p1);

//打印p1指针的地址

printf(“p1=%d”,p1);

}

在java里面可以retrun出来,但是这样效率会低一些

指针类型变量的长度

指针类型的变量长度都是一致的

void main(){

printf(“int*占%d个字节\n”,sizeof(int*));

printf(“double*占%d个字节\n”,sizeof(double*));

}

结果如下:

int*占4个字节

double*占4个字节

64位编译器为8个字节

静态内存分配和动态内存分配

静态内存分配:

系统统一分配 统一回收 占内存大小固定

char * function

(){

char array[]={

‘a’,’b’,’c’,’d’};

//返回首地址

printf(“array的首地址%#x\n”,&array);

return &array[0];

}

char *function2(){

char array[]={‘d’,’b’,’c’,’a’};

printf(“%#x\n”,&array);

return &array[0];

}

void main(){

char*p=function();

//有返回值的函数不一定要写返回值;

function2();

printf(“%d,%d,%d\n”,p,(p+1),*(p+2));

printf(“%d,%d,%d\n”,p,(p+1),*(p+2));

}

定义一个方法会在栈内分配内存,使用完后会被回收。

动态内存分配:

include

include

结构体

大小:大于或者等于每一个元素大小的和 而且是最大的元素所占节数的整数倍

//c中结构体不能直接定义函数

//要使用函数就用函数指针

函数指针 定义方式: 返回值(*函数指针名字)(形参){

函数指针指向的函数 要跟函数指针定义的返回值和形参类型保持一致

}

结构体的指针

/*

struct 结构体

在java中相当于是class

*/

age=220;
printf("%d",(*stup).age);
//方法这里一直报错
//第一个错误是没有声明指针方法,第二个错误是没有加括号
stup->studyP();
}" data-snippet-id="ext.99d32e0e483e2424a2ff2d149caf36d1" data-snippet-saved="false" data-codota-status="done">[code]void study(){
printf("好好学习 天天向上");
}

struct Student{
float score;//4
short age;//2
char sex;//1
//c中结构体不能直接定义函数
//要使用函数就用函数指针
//函数指针的定义方式:返回值()(形参)
void (*studyP)();
}

main(){
struct Student stu = {2.2f,22,'f',&study};
stu.age=20;
//调用函数时编译器报错
stu.studyP();
printf("%d\n",stu.age);
//看结构体的大小
printf("%d\n",sizeof stu);

//采用结构体指针来调用结构体里面的方法和函数
/*通过结构体类型的定义
struct Student* A=结构体的地址
直接引用和间接引用
*/
//直接引用
struct Student * stup =&stu;
(*stup).age=110;
printf("%d\n",(*stup).age);
//间接引用
stup->age=220;
printf("%d",(*stup).age);
//方法这里一直报错
//第一个错误是没有声明指针方法,第二个错误是没有加括号
stup->studyP();
}


联合体

include

include

枚举

//声明枚举类 enum 定义枚举类 类型的取值范围只能从枚举值中取

//typedef type define

enum WeekDay{

//设置a为1 则从一开始递增

a=1,b,c,d,e,f

};

main(){

//调用枚举类

enum WeekDay day1=a;

enum WeekDay day4=d;

printf(“%d\n”,day1);

printf(“%d\n”,day4);

}

(注意枚举类的声明形式)

自定义类型

在jni中 typedef void* jobject;

给任意类型的指针void* 起别名为jobject

typedef jobject jclass;

typedef jobject jarray;

typedef jarray jobjectArray;

其实都是表示void* 实质上是为了增强代码的可读性表示在java那边处理的是那种的数据类型

c知识点复习完之后就可以做JNI了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: