栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言学习笔记(浙大翁恺版)第九周(指针部分)(2)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言学习笔记(浙大翁恺版)第九周(指针部分)(2)

9.2.1 指针运算 1+1=2?
char ac[]={0,1,2,3,4,5,6,7,8,9,};
char *p = ac;

printf("p  =%pn",p);
printf("p+1=%pn",p);

  •  两个地址相差1
int ai[]={0,1,2,3,4,5,6,7,8,9,};
int *q = ai;

printf("q  =%pn",q);
printf("q+1=%pn",q);

  • 两个地址相差4

为何如此?很简单,char变量占据一字节而int类型占据4字节。指针加一,增加的是sizeof(char/int/double...)

给指针加一表示要让指针指向下一个变量。

在讲到数组和指针的关系时,我们提到可以将指针当作数组操作,也可以将数组当作指针操作。那么我们试试用*操作符。

  • *p等价于ac[0]
  • 那么*(p+1)等价于ac[1]
char ac[]={0,1,2,3,4,5,6,7,8,9,};
char *p = ac;

printf("p  =%pn",p);
printf("p+1=%pn",p);

printf("*p+1=%pn",*(p+1));

因此*(p+n)< == >ac[n]

tips:如果指针不是指向一片连续分配的空间,比如数组,那么这种运算就没有意义了

指针运算
  • 这些算术运算可以对指针做
    • 指针加减一个整数:+、-、+=、-=
    • 指针递增或递减:++、--
    • 两个指针相减:此时得到的结果是(地址差/sizeof()),注意要以%d输出结果
int ac[]={0,1,2,3,4,5,6,7,8,9,};
int *p = &ac[0];
int *p1= &ac[5];

printf("p  =%pn",p);
printf("p+1=%pn",p+1);
printf("p1-p=%dn",p1-p);

 

*p++
  • ++的优先级要比*高
  • 因此先执行p++然后取地址,但是由于++在调用后才执行
  • 所以其作用是,取出p的地址,再将p移动到下一位
    • 适用于数组类的连续空间操作(如遍历)
    • 在一些cpu上可以被直接翻译为一条汇编语言

之前的遍历操作:

int ac[]={1,2,3,4,5,6,};
int *p=&ac[0];

for(int i=0;i 

 现在的遍历操作:

int ac[]={1,2,3,4,5,6,-1};
int *p=&ac[0];

//写法1
for(p=ac;*p!=-1;p++)
{
    printf("%dn",*p);
}
//写法2
for(p=ac;*p!=-1;)
{
    printf("%dn",*p++);
}
//写法3
while(*p!=-1)
{
    printf("%dn",*p++);
}

指针比较
  • <、<= 、==、 >、 >=、 !=  都可以对指针做
  • 实际上是比较它们在内存中的地址
  • 数组中单元地址是线性递增的

0地址 

在计算机运行时会给所有进程分配一块虚拟内存,其特征是地址从0开始,但是0地址是不能随便碰的!0地址不能被写入,有些甚至不能读取。因此你的指针不应该具有0值.

然而0地址可以用来表示一些特殊的东西:

  • 返回0值代表返回的指针是无效的
  • 定义指针变量时先让指针指向0,这意味着指针没有被真正初始化
  • C语言定义了一个符号NULL来表示0地址(一些编译器不想让你用0来表示0地址)

指针的类型 
  • 无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
  • 但指向不同类型的指针不能直接相互赋值,这是为了避免用错指针

指针类型转换
  • void* 表示指针不确定指向什么东西,但是指向一块内存空间
  • 强制类型转换 
int *p = &i;
void *q = (void*)p;

此处将p强制转换为void型指针。这并没有改变p指向的变量的类型,而是通过q去看指向的变量时,不再将i看作int类型而是void类型。

总结一下,用指针可以做什么 

9.2.2 动态内存分配

C99里可以用变量定义数组大小,而C99之前人们使用动态内存分配:

malloc函数

malloc(size_t size) ; 返回的类型是void* (因为类型是无法传递的),需要额外类型转换

  • 要使用该函数需要包含头文件
  • 向malloc申请的空间大小是以字节为单位,要申请多少,括号里写数量*sizeof(需要的类型)
  • 使用结束后要释放申请的空间,使用free()函数
  • 返回的结果是void*,需要转换为自己需要的类型(类型是人为将数值定义的种类)
    • eg:要申请数量为n,int类型的,返回类型为int*的空间给一个指针变量a
    •  int *a; a=(int*)malloc(n*sizeof(int));
#include
#include

int main(void)
{
int number;
int *a;
int i;

printf("请输入变量:");
scanf("%d",&number);
//C99可以直接写 int a[number];

a=(int*)malloc(number*sizeof(int));

//读入数据
for(i=0;i=0;i--)
{
    printf("%d",a[i]);
}
free(a);//申请了一块空间,现在需要释放。程序将指针当作数组用,所以直接释放a即可

return 0;

}
申请失败
  • 如果申请内存失败则会返回0(或者称为NULL)
  • 你的系统能给你多大的空间?用下列代码试一下吧!
#include
#include

int main(void)
{
void *p;
int cnt=0;

while((p=malloc(100*1024*1024)))
{
cnt++;
}

printf("分配了%d00MB的空间n",cnt);

return 0;
}

 while((p=malloc(100*1024*1024)))

这条语句同时做了两件事,第一:申请100MB空间给p;第二:将p值作为while条件

这样在申请失败,也就是没有可申请空间时循环停止,可以得出系统最大可分配的内存值。

 free()
  • 俗话说有借有还,再借不难,free函数的作用就是将借来的内存空间还给系统,只需要将空间首地址传入free即可
  • 申请过的空间最终都是需要还回去的
  • free(NULL); 完全没问题,相当于啥也没做。或者是形成一个习惯:定义指针时,先给指针赋0值。如果没有申请或者申请失败,此时就free(NULL),free(0)

常见问题 

申请了却没有free

  • 后果是长时间运行内存会逐渐减少
    • 新手可能是忘记了
    • 进阶者可能是找不到合适的free时机

free了多次

  • 会崩溃

地址改变后直接free 

  • 比如申请的是指针p,执行free(p++)会提示p++所指的变量没有申请 

因此有一个malloc就要配套一个free。需要对程序结构有一定的规划,还需要一些经验。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/862391.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号