一、函数指针
-
1.函数指针基本定义
int plus(int a, int b){ return a + b; } int main(){ int result; //函数的返回值 //定义函数指针 int(*calc)(int a, int b); calc = plus; //给指针赋值 result = calc(3, 5);//调用函数指针 printf("minus:%#x\n", minus); //函数名打印出来是一个函数的首地址,所以我们可以将函数赋值给对应类型的函数指针 printf("result:%d\n", result); system("pause"); return 0; }
2.void类型指针 与强制转换
int plus2(int *a, int *b){
return *a + *b;
}
//函数名是一个函数的首地址,所以我们可以将函数赋值给对应类型的函数指针
int main(){
int result; //函数的返回值
int c = 3;
int d = 5;
int(*calc2)(void *, void *);//定义函数指针
//void类型的指针,类似java里面的object
//指针变量都是4个字节。都是十六进制表示。
//void*-> int * /char * /float *
//类型不匹配 强制类型转换
calc2 = (int(*)(void *,void *))plus2;
result = calc2(&c,&d);
printf("result:%d\n", result);
system("pause");
return 0;
}
-
3.多态
int plus2(int *a, int *b){ return *a + *b; } int minus2(char *a, char *b){ return 0; } //函数名是一个函数的首地址,所以我们可以将函数赋值给对应类型的函数指针 int main(){ int result; //函数的返回值 int c = 3; int d = 5; //定义函数指针 int(*calc2)(void *, void *); calc2 = (int(*)(void *, void *))minus2; //向下转型 result = calc2(&c,&d); //调用函数 printf("result:%d\n", result); system("pause"); return 0; }
二、内存分配
- 1.malloc函数,动态申请大数组
//函数 void* malloc(size_t size)
//分配内存的单元是字节,大小为size的连续空间 返回值为 void*
int main(){
//定义大数组存在在堆内存中(因为数组很大占内存会溢出)
int *a = (int*)malloc(sizeof(int)*1024*1024*10);
//动态申请的内存一定要手动释放不然会内存泄漏
//原则:1.free不能重复释放,
// 2.必须赋值NULL
// 3.申请和释放要一一对应,
//如:申请了一个4M的数组a 之后又将a指向一个8M的空间 导致4M的内存被一直标记为使用状态无法回收
free(a); //释放内存空间
a=NULL; //赋NULL,如果不赋NULL a的地址还存在但是变成了一个野指针。
system("pause");
return 0;
}
-
2.申请超大内存的数组
//如果申请过大的内存malloc函数会返回一个空的指针 申请失败 //如果申请更大会造成int的最大值溢出 int *a = (int *)malloc(sizeof(int) * 1024 *1024 *500) if(a = NULL){ printf("内存不够"); } printf("%#x", a); system("pause");
-
3.calloc函数,动态申请大数组
//void* calloc(size_t Count,size_t Size) //申请count个大小为size的连续空间,这个连续空间的大小是size,而不是_Count * siz同时他会初始化,将所有的变量全部初始化为0,如果返回值为NULL表示申请失败。 int *b = (int *)calloc(4,100*sizeof(int)); if(b==NULL){ //使用时一定要做非空判断 frintf("内存不够\n"); } printf("%#x",b); //动态申请的内存一定要手动释放不然会内存泄漏 //原则:1.free不能重复释放, // 2.必须赋值NULL // 3.申请和释放要一一对应, //如:申请了一个4M的数组a 之后又将a指向一个8M的空间 导致4M的内存被一直标记为使用状态无法回收 free(b); //释放内存空间 b=NULL; //赋NULL,如果不赋NULL a的地址还存在但是变成了一个野指针。 system("pause");
三、字符串
C语言里面没有String 用char 来表示String
- 1.char类型的数组表示String
字符串定义一:
char ch1[10] = {'c','h','i','n','a'};
printf("%s\n",ch1);
在printf中占位符%s 他会接收一个字符串的地址,从地址里面获取所有的字符串打印,系统会在最后自动加上要给'\0'(空格)的结束标记。
字符串定义二:
char ch1[] = {'c','h','i','n','a','\0'};
这样定义没有定义数组长度就一定要加上结束标记'\0',不然会出现乱码。
字符串定义三:
char ch1[20] = "china"; //将一个常量赋值给ch1
ch1本身是一个常量,C语言初始化的时候会将"china" copy给ch1常量所指向的空间
ch1[0] = 's' ;
ch1本身是一个常量存储的是一个地址是不能修改的但是ch1[0]表示的是地址指向的区域所以可以修改
字符串定义四:指针表示
char *ch = "china";
工作过程:
1.分配一个常量区存储:“string”;
2.char*ch 没有初始化的char类型的指针变量。
3.赋值:将常量区A的首地址赋值给ch
ch[2] ='b'; //发现无法修改,因为china 是一个常量 编译器帮我们在常量区找了一块地址存储,所以ch指向的是一块常量区,所以常量区无法修改
char *ch = (char*)malloc(100*sizeof(char));
free(ch);
ch = NULL;
ch = china;
char *ch = (char*)malloc(100*sizeof(char));
strcpy(ch,"china"); //需要使用strcpy接口才能修改字符串中的内容,原理是将china常量中的内容一一复制到ch中
- 2.字符串函数大全
详细示例: day03_ndk2_C语言字符串函数.doc
stpcpy 拷贝一个字符串到另一个
strcat 字符串拼接函数
strchr 在一个串中查找给定字符的第一个匹配之处
strcmp 串比较
strncmpi 将一个串中的一部分与另一个串比较, 不管大小写
strcpy 串拷贝
strcspn 在串中查找第一个给定字符集内容的段
strdup 将串拷贝到新建的位置处
stricmp 以大小写不敏感方式比较两个串
strerror 返回指向错误信息字符串的指针
strcmpi 将一个串与另一个比较, 不管大小写
strncmp 串比较
strncmpi 把串中的一部分与另一串中的一部分比较, 不管大小写
strncpy 串拷贝
strnicmp 不注重大小写地比较两个串
strnset 将一个串中的所有字符都设为指定字符
strpbrk 在串中查找给定字符集中的字符
strrchr 在串中查找指定字符的最后一个出现
strrev 串倒转
strset 将一个串中的所有字符都设为指定字符
strspn 在串中查找指定字符集的子集的第一次出现
strstr 在串中查找指定字符串的第一次出现
strtod 将字符串转换为double型值
strtok 查找由在第二个串中指定的分界符分隔开的单词
strtol 将串转换为长整数
strupr 将串中的小写字母转换为大写字母
swab 交换字节
PS:isalpha()是字符函数,不是字符串函数
知识要点
-
函数指针定义的注意事项
//下面两个表达式完全不同 int(calc*)(void * ,void *) ; //这是函数指针 int* p(int a ,int b); //这是要给返回值是int* 的函数(因为()的优先级比*的优先级高)
-
内存分区:
1. 程序区 :存储程序的二进制文件 2. 静态存储区:存储全局变量和静态变量 3. 动态存储区: 堆区:用于程序动态分配的内存(很大) 栈区:编译器自动分配,编译器自动申请和释放(一般只有2M左右)