目录
1、malloc,calloc 和 realloc 的作用及区别
C语言 (复习)
1、malloc,calloc 和 realloc 的作用及区别
-
malloc 使用的最频繁,因为它最简单,只需要一个参数,即需要动态开辟的内存的字节数,
如果堆里的连续空间能满足需要则将分配好的内存首地址返回,否则返回 NULL。
-
calloc 只是在 malloc 的基础上将分配好的每个字节赋值为 0,这个功能使用并不多见,
但由于 callloc 需要提供两个参数,相比较而言并没有 malloc 使用的多。
-
realloc 主要用于需要修改动态内存大小的场景,比如原本开辟了 100 个字节,现在需要 200 个字节。
- free,用于释放内存,主要注意 free 可能引发程序崩溃的几个原因,
1、越界;
2、移动指针的指向,free 时指针不指向动态内存的开头;
3、重复释放同一段内存;
4、释放不是动态创建的内存。
2、static 关键字的用法及作用
在 C 语言中,static 主要定义全局静态变量,定义局部静态变量,定义静态函数
- 定义全局静态变量 :在全局变量前面加上关键字 static,该全局变量变成了全局静态变量。
全局静态变量有以下特点:
- 在全局数据区内分配内存
- 如果没有初始化,其默认值为 0
- 该变量在本文件内从定义开始到文件结束可见
- 定义局部静态变量:在局部静态变量前面加上关键字 static,该局部变量便成了静态局部变量。
静态局部变量有以下特点:
- 该变量在全局数据区分配内存
- 如果不显示初始化,那么将被隐式初始化为 0
- 它始终驻留在全局数据区,直到程序运行结束
- 其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
- 定义静态函数:在函数的返回类型加上 static 关键字,函数即被定义成静态函数。
静态函数有以下特点:
- 静态函数只能在本源文件中使用
- 在文件作用域中声明的 inline 函数默认为 static
说明:静态函数只是一个普通的全局函数,只不过受 static限制,他只能在文件所在的编译单位内使用,不能在其他编译单位内使用。
在 C++语言中新增了两种作用:定义静态数据成员或静态函数成员
- 定义静态数据成员。
静态数据成员有如下特点:
- 内存分配:在程序的全局数据区分配
- 初始化和定义:静态数据成员定义时要分配空间,所以不能在类声明中定义
- 静态成员函数。静态成员函数与类相联系,不与类的对象相联系。静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例,主要用于对静态数据成员的操作。
- 静态成员函数和静态数据成员都没有 this 指针。
3、指针和数组的区别
- 大小不同,指针在 32 位平台 4 字节,64 位平台(x64)8 字节,
而数组的大小为数组长度*sizeof(数组单元格)。由此可以得到求数组 arr 长度的公式为 sizeof(arr)/sizeof(arr[0]);
- 访问权限不同,数组名 arr 永远指向数组的开头元素,不能移动,
指针 p 的值可以发生改变。例如 arr++错误,p++正确;
- 访问方式不同。数组和指针在很多情况下可以互换,
例如 arr[i] == *(arr+i), *(p+i)==p[i]。 但实际上它们的具体访问不同。
arr[i]是在数组名完后偏移 i 个单元格,然后取值,
而 p[i],是把 p 的值先加 i,然后再跳到该地址上取值
指针数组与数组指针:
- 指针数组:int *p[4] ,存放指针的数组,实际是一个数组;
- 数组指针:int (*p)[4],指向数组的指针,实际是一个指针。
4、大端和小端
- 小端:低地址存放低字节(小)数据。 eg:PC
- 大端:低地址存放高字节(大)数据。 eg:网络、手机
考点:如何通过代码判断当前系统是大端还是小端?
bool is_big()
{
short int a = 0x1234;
char b = *(char *)&a; //通过将 int 强制类型转换成 char 单字节,通过判断起始存储位置。
//即等于取 b 等于 a 的低地址部分
if( b == 0x12)
{
return true;
}
return false;
}
5、二分(折半)查找
概念:二分查找也称为折半查找,是最著名的查找算法,优点:是算法简单易实现,查找速度快,平均性能好,时间复杂度仅为 O(logn),缺点:是数据必须顺序存储且有序。
//arr 数组名,len 数组长度,key 需要查询的关键字
//成功返回下标,失败返回-1
int BinSearch(const int *arr,int len,int key) //O(logn)
{
int low = 0; //起始下标
int high = len-1;//结束下标
int mid; //中间下标
while(low <= high)
{
mid = (low+high)/2; // 取中间值
if(arr[mid] == key)
{
return mid;
}
else if(arr[mid] < key) //需要在更大数据那边找
{
low = mid + 1;//
}
else //需要在更小数据那边找
{
high = mid - 1;
}
}
return -1;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10}; //测试用例
for(int i=0;i<12;i++)
{
printf("%d\n",BinSearch(arr,sizeof(arr)/sizeof(arr[0]),i));
}
return 0;
}
6、实现 Myatoi 函数
思路:实现 Myatoi 函数,将字符串转成数字,比如 "123"->1 2 3,"12a3"->1 2。遇到第一个非数字字符转换结束。可以处理前面的空格字符和负号。
int Myatoi(const char *str)
{
assert(str != NULL);
if(str == NULL)
{
return 0;
}
int tmp = 0;//保存数值
int flg = 1;//保存正负符号
while(*str == ' ')//消除前面的空格
str++;
if(*str == '-')//读取符号
{
flg = -1;
str++;
}
else if(*str == '+')
{
str++;
}
while(isdigit(*str))//处理数字字符
{
tmp = tmp*10 + (*str - '0');
str++;
}
return flg*tmp;
}