C语言第八章——指针(二)
指针运算
注:之前已经说到,把数组赋给指针以后,可以拿数组像指针一样操作,也可以拿指针像数组一样操作
//数组像指针一样操作
char ac[]={0,1,2,3,4,5,6,7,8,9};
int *p=ac;
int *p1=&ac[5];
//指针像数组一样操作
*p->ac[0]
*(p+1)->ac[1]
*(p+n)->ac[n]
//*(p+1)要加括号是因为*是单目运算符,优先级比+高
- 对指针加1的时候,不是在地址上加1,而是在地址上加一个sizeof那个指针所指的类型,即移到下一个单元上
- 但如果指针不是指向一片连续分配的空间,如数组,则这种运算没有意义(好理解)
int *p=ac;
和int *p1=&ac[5];
,int *p=ac;
可以不写取地址符,和int *p=&ac[0];
是一回事,但是int *p1=&ac[5];
必须要写,这个要特别注意的*(p+1)
和*p+1
不一样,要理解p1-p
是什么?两个指针的相减,最后结果是5,这是两个值相减,再除以sizeof那个类型,即是说中间差了几个数组单元*p++
是什么意思?是取出p所指的那个数据来,完事以后顺便把p移到下一个单元,注意,*的优先级虽然高,但是没有++的优先级高,这常用于数组类的连续空间操作
以遍历数组为例,其实两种写法本质上是一样的
#include<stdio.h>
int main()
{
char ac[]={0,1,2,3,4,5,6,7,8,9};
//遍历数组 方法1
int i;
for(i=0;i<sizeof(ac)/sizeof(ac[0]);i++)
{
printf("%d\n",ac[i]);
}
//遍历数组 方法2
//这时候应该在数组中多一个不能达到的值,比如-1
char ac1[]={0,1,2,3,4,5,6,7,8,9,-1};
char *p=ac1;
while(*p!=-1)
{
printf("%d\n",*p++);
}
return 0;
}
动态内存分配
动态内存分配在什么时候用?
C99以前,确定需要多大的单元的时候
#include<stdio.h>
int main()
{
int number;
printf("输入数量:");
scanf("%d",&number);
int a[number];//就是为了解决这件事情
//因为C99以前不能在方括号中加数字
return 0;
}
如上代码
但注意:malloc是必须掌握的东西
详细介绍怎么用
三部曲:
-
#include<stdlib.h>
这个头文件要加上 -
a=(int *)malloc(number*sizeof(int));
这句话的意思是,先讲你需要多少个number,然后乘以你需要的数据类型的大小,就是 你所需要的内存的大小,malloc(你所申请的内存的大小(字节)) ,但是由于只是给你了这片内存,即这篇内存现在没有明确的类型,是void *,因此要再强制类型转换成int * 这一块因为是连续的空间,就可以当成a是数组,进行操作了
-
free(a)
释放的应该是原来的地址
样例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int number;
int *a;
int i;
printf("输入数量:");
scanf("%d",&number);
/*
int a[number];//就是为了解决这件事情
//因为C99以前不能在方括号中加数字
*/
a=(int *)malloc(number*sizeof(int));
for(i=0;i<number;i++)
{
scanf("%d",&a[i]);
}
for(i=number-1;i>=0;i--)
{
printf("%d",a[i])
}
//数组和指针 能不能混着用取决于是不是一片
//连续的空间
//上面赋值的语句块和逆序输出的语句块完全是按照数组来做的
free(a);
//如果申请失败就会返回0,或者就是NULL
return 0;
}
malloc能给我们分配多大的空间
#include<stdio.h>
#include<stdlib.h>
int main()
{
void *p;
int cnt=0;
while((p=malloc(100*1024*1024))) //每次申请100MB的空间,如果最后输出3300MB,就是只能申请33次100MB,也就是只能给你3300个MB的空间
{
cnt++;
}
printf("分配了%d00MB的空间",cnt);
return 0;
}
这里需要注意的几点
- p为什么是
void *
,因为malloc()本身就是void *
,然后再看你的需要来强制类型转换成你需要的 - 三部曲中说的就可以把a当成数组用了,其实还是因为a是个地址,其实应该
*a,*(a+1),*(a+2)
这样子用,但是为啥可以变成a[0],a[1],a[2]
,上一节笔记中已经详细的总结清楚了 free()
只能还首地址(借啥还啥),因为这一片地址空间是以这个首地址代表的,这就像数组一样,要有一个代表这片空间的名儿,还这个名儿就行- 可以
free(NULL)
。原因是编程的好习惯是定义一个指针就初始化为NULL,类似变量习惯初始化为0一样,只是因为它是指针变量所以初始化为NULL
,然后free
了个NULL
,意思就是不做事情嘛,具体的理解可以理解成,大家都去还东西,必须要借什么还什么(体现在只能还申请来空间的首地址),但是如果你跟它说,我就是来这和你说一声,我没借(其实就是free(NULL)
的意思了)