一、一级指针与一维数组
把指针充当变量的用法,在C/C++的数据结构学习中广为应用,这种用法学习起来是比较简单的。 先看代码。这里的代码,有string.h头文件包含的函数,和scanf,这两者在正常的写法中不用加“_s”,这篇随笔所及代码的运行环境是Visual Studio2017,编译器会把scanf等函数增强,因此为了正常运行,会加上“_s”.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
int main() {
//把指针充当变量的方式有两种
//1. 通过变量的地址初始化
int num = 1;
int *pInt = #
*pInt = 101; //这里的*pInt等效于num
printf("*pInt=%d\tnum=%d\n", *pInt, num);
//2.1. 通过使用malloc初始化内存,让指针变成普通变量
int *p = (int *)malloc(sizeof(int));
if (p == NULL) {
return 0;
}
*p = 101;
printf("*p=%d\n", *p);
free(p);
p = NULL;
//2.2 可以把指针变成数组,一级指针则成为一维数组
int *array = (int *)malloc(sizeof(int ) * 3);
if (array == NULL) {
return 0;
}
for (int i = 0; i < 3; i++) {
scanf_s("%d", array + i); //把从键盘输入的字符存储到数组中
//array[i] = i; 自动添加数字元素到数组中
printf("arr[%d]=%d,arr[%d]=%d\n", i, array[i], i, *(array + i));
}
free(array);
array = NULL;
//3. 指针作为字符数组
char *pChar = (char *)malloc(sizeof(char) * 27);
for (int i = 0; i < 26; i++)
{
pChar[i] = 'A' + i;
printf("%c\t", pChar[i]);
}
printf("\n");
//3.1 字符数组,字符串的区别
pChar[26] = '\0';
printf("%s\n", pChar);
printf("\n");
free(pChar);
pChar = NULL;
//3.2 关于字符数组赋值的问题,C语言中没有string类型
char *pStr = (char *)malloc(sizeof(char) * 10); //pStr[10];
/*
字符串的赋值只能通过两种方式
1. 字符串采用字符的方式去处理
2. 通过字符串拷贝函数去赋值
*/
strcpy(pStr, "Loveyou");
printf("%s\n", pStr);
free(pStr);
pStr = NULL;
//3.3 申请的数组长度可以为一个变量
printf("你想输入多少个学生信息:");
int count = 0;
scanf_s("%d", &count);
float *pScore = (float *)malloc(sizeof(float)*count);
printf("请输入%d个学生成绩\n", count);
for (int i = 0; i < count; i++)
{
scanf("%f", pScore + i);
}
for (int i = 0; i < count; i++)
{
printf("%f\t", pScore[i]);
}
printf("\n");
free(pScore);
pScore = NULL;
system("pause");
return 0;
}
把指针充当变量的用法有两种: ①:通过变量的得地址初始化; ②通过使用malloc初始化内存,让指针变成普通变量。
1.1通过变量的地址初始化
如代码中1.1的例子所写,定义一个普通变量并初始化,然后定义一个指针变量,通过取地址符号取到普通变量num的值,赋值给指针,此时指针变量 *pInt等效于变量num,在后面修改num的值的时候可以直接用指针变量来修改。这部分其实没什么好讲的,很简单。
2.1使用malloc函数使指针变量变成普通变量
申请一个存储int类型变量的内存,写法大概的如下:
int *p = (int *)malloc(sizeof(int));
格式: 基本数据类型 *指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)) 注意两点: ① 在正式编程中我们要用防御式编程的思想; ②在申请且使用了内存后,要及时释放内存,释放步骤为
free(指针变量名字);
指针变量名=NULL;
2.2使用 malloc申请一段内存
方式大概如下:
int *array = (int *)malloc(sizeof(int ) * 3);
格式: 基本数据类型 指针变量名 = (强制转换类型)malloc(sizeof(基本数据类型)需要申请的长度) 在例子2.2中,再复习一遍之前学过的内容,用array[i]和*(array+i)两种方式分别遍历一遍整形数组。
2.3 使用malloc申请字符类型的内存
方式大概如下:
char *pChar = (char *)malloc(sizeof(char) * 27);
我们用26个字母作为字符数组遍历。 这里需要注意的是: ①C语言中,字符数组是按照字符串来处理的; ②字符串的末尾,需要在字符串最后一位加上"\0"来结尾; ③字符数组和字符串是有区别的,因此用 %c而不是%s ④申请字符类型空时,代码中的27可以用变量替换掉。如替换成count。 第二条,我们可以把循环遍历中的
printf("%c\t", pChar[i]);
pChar[26] = '\0';
这两行代码用注释掉和不注释两种情况来比较,得出结论,如下两张图。 注释掉后的结果: 不注释的结果: 明显的,在注释掉循环中的打印代码后,通过比较有无字符串结尾处理得出结论。 第四条的写法,如上面代码所示,这一部分没有需要注意的东西,不做阐述。
二、二级指针与二维数组
这里说明,二级指针并不能直接转成二维数组,二维数组中的元素都是普通变量,而二级指针指向的地址,存储的是一级指针变量的地址。 附上一张图
这部分的讲解基本都在代码块的注释里,复制到文本文件里食用口味更加。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//1.2 通过返回值申请内存,这是一个申请数组的函数
int *Mallo_Array(int arrLength) {
int *array = (int *)malloc(sizeof(int *)*arrLength);
return array; //返回数组首地址
}
//1.3 通过参数申请内存
void malloc_Array1D(int **array, int arrLen) {
//通过一级指针修改普通变量的值,因此改变普通变量时候传递一级指针
//通过二级指针修改一级指针的指针变量,因此改变指针指向的时候要传递二级指针
*array = (int *)malloc(sizeof(int *)*arrLen);
}
//1.4 字符串当做函数参数,申请内存
//通过外部变量来初始化字符串,如申请一个内存存储字符串,可能传一个常量,而常量是不能修改的,因此要申请一段内存来保存常量
//这里不用malloc而是用 strlen,因为fileName只是一个指针,用malloc申请到的永远是4个字节
void malloc_String(const char *fileName) {
char *pStr = (char *)malloc(strlen(fileName) + 1); //计算长度,此处字符串数组长度要+1
strcpy(pStr,fileName); //使用strcpy来赋值,把fileName拷贝到pStr中就可以对fileName进行修改操作
printf("%s", pStr);
}
int main() {
//1.1 二级指针和二维数组
int *pInt = (int *)malloc(sizeof(int) * 3); //意味着每一个SecPointer[i]都是一个一级指针
int **SecPointer = (int **)malloc(sizeof(int *) * 9); //开辟九个长度的存放一级指针变量的数组
for (int i = 0; i < 9; i++) {
SecPointer[i] = (int *)malloc(sizeof(int) * 9); //为九个指针申请内存使其成为二维数组
}
SecPointer[7][7] = 101;
printf("%d\n", SecPointer[7][7]);
free(SecPointer);
SecPointer = NULL;
//1.2 调用函数申请一个容量为3的一维数组
int *array = Mallo_Array(3);
for (int i = 0; i < 3; i++) {
array[i] = i;
printf("array[%d]=%d,array[%d]=%d\n", i, *(array+i),i,array[i]);
}
free(array);
array = NULL;
//1.4
malloc_String("LoveYou");
printf("\n");
system("pause");
return 0;
}
下面是运行结果。
三、malloc,realloc,calloc
上代码。
#include<stdio.h>
#include<stdlib.h>
//1.1 calloc函数在申请内存后会默认初始化
//1.2 realloc函数可在内存不足的情况下重新申请内存,且具有复制功能,即会把原来内存里的元素再复制到新申请的内存中
int main() {
//1.1
int *pCalloc = (int *)calloc(3, sizeof(int));
int *pMalloc = (int *)malloc(sizeof(int) * 3);
for (int i = 0; i < 3; i++) {
printf("Calloc[%d]=%d\n", i, pCalloc[i]);
}
printf("\n");
free(pCalloc);
pCalloc = NULL;
for (int j = 0; j < 3; j++) {
printf("Malloc[%d]=%d\n", j, pMalloc[j]);
}
printf("\n");
free(pMalloc);
pMalloc = NULL;
//1.2
int *pMall = (int *)malloc(sizeof(int) * 3);
for (int x = 0; x < 3; x++) {
pMall[x] = x;
}
realloc(pMall, sizeof(int) * 6);
for (int y = 3; y < 6; y++) {
pMall[y] = y;
}
for (int z = 0; z < 6; z++) {
printf("%d", pMall[z]);
}
system("pause");
return 0;
}
需要注意的是realloc,calloc,malloc在写法上的不同 ,三者分别两两放在一起比较:
int *pCalloc = (int *)calloc(3, sizeof(int));
int *pMalloc = (int *)malloc(sizeof(int) * 3);
int *pMall = (int *)malloc(sizeof(int) * 3);
realloc(pMall, sizeof(int) * 6);
可以看到calloc函数和malloc在申请内存时候的写法,只在后面部分的顺序不同;而realloc和malloc相比,则有很大的不同,这是因为他们的功能上有很大的差别: ①malloc:申请内存,不进行初始化; ②calloc:申请内存,并进行初始化,初始化为0; ③realloc:当之前申请的内存不足时候,重新申请内存,且申请的内存应为原来内存的整数倍。realloc在申请内存后,会把原内存的内容复制到新内存中。 下面是运行结果。
显而可见,calloc会自动将数组中的内容初始化为0,而malloc不会。在实际应用中,malloc的应用会比calloc多得多。而realloc通过使用前和使用后两种情况,将其打印输出,也可以很清晰的了解其功能。 为了更加清楚地明白realloc的运行机制,画图。 暂时到这里。 **
球球了,给点个赞吧 !(>-<)!
**