作者 | 五道杠的小屁孩wwk

责编 | 夕颜

出品 | CSDN博客

学习C肯定会碰到指针,指针是C的灵魂。所以学好指针很关键,这里写一些指针方面的容易错的或者易混淆的知识点还有自己不会的盲点,以便之后复习时用。

数组传参和数组形参

1.1 数组传参

如果函数遇到数组传参的,不论是什么形式的形参,只要是数组,那么被调函数都将这个形参都当做指针来使用。

#include "stdio.h"PrintArray(int *a, int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}int main(void)
{int a[] = { 3,4,5,6,7,7,8 };int num = sizeof(a) / sizeof(a[0]);
PrintArray(a, num);system("pause");
}

一般我们使用数组传参。

下面还有一种形参表示方法也很常用,效果其实是一样的。

#include "stdio.h"PrintArray(int *a, int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}PrintArray1(int a[], int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}
int main(void)
{int a[] = { 3,4,5,6,7,7,8 };int num = sizeof(a) / sizeof(a[0]);
PrintArray(a, num);PrintArray1(a, num);
system("pause");
}

甚至还有一种方法:

#include "stdio.h"PrintArray(int *a, int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}PrintArray1(int a[], int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}PrintArray2(int a[7], int num)
{
int i;
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}
int main(void)
{int a[] = { 3,4,5,6,7,7,8 };int num = sizeof(a) / sizeof(a[0]);
PrintArray(a, num);PrintArray1(a, num);PrintArray2(a, num);
system("pause");
}

1.2 数组传参实质

数组实质传的都是指针,不论什么表现形式。

#include "stdio.h"PrintArray(int *a, int num)
{
int i,num1;
num1 = sizeof(a) / sizeof(a[0]);
printf("num = %5d",num1);for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}PrintArray1(int a[], int num)
{
int i,num1;
num1 = sizeof(a) / sizeof(a[0]);
printf("num = %5d", num1);
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}PrintArray2(int a[7], int num)
{
int i,num1;
num1 = sizeof(a) / sizeof(a[0]);
printf("num = %5d", num1);
for (i = 0; i < num; i++)
{
printf("%5d", a[i]);
}
printf("\n");
}
int main(void)
{int a[] = { 3,4,5,6,7,7,8 };int num = sizeof(a) / sizeof(a[0]);
PrintArray(a, num);PrintArray1(a, num);PrintArray2(a, num);
system("pause");
}

可以看到num1的值均为1。

实参都是数组,形参都是指针,无论什么形式。

数组首元素地址和整个数组地址

#include "stdio.h"int main(void)
{
int a[10];printf("a的大小 = %d\n", sizeof(a));printf("a = %d\n", a);printf("a + 1 = %d\n", a + 1);printf("&a = %d\n", &a);printf("&a + 1 = %d\n", &a + 1);
system("pause");
}

从这组输出我们可以看到几点:

  • a数组大小是40。因为一个int是4字节,一共10个。

  • 数组a和&a值一样

  • 但是a是数组首元素地址,而&a是整个数组地址。

  • 这个原因也导致另外两个值不同。a+1就是第二个元素地址,偏移4字节

  • &a+1是相当于偏移整个数组大小,也就是40字节。

变量在内存中的位置

变量在内存中有四个地方可以存放,读取修改变量实质都是通过指针修改。

3.1 变量存放的区域

3.2 常量例子

#include "stdio.h"char *GetChar1(void)
{
char *p1 = "abcdefg";
return p1;
}char *GetChar2(void)
{
char *p2 = "abcdefg1";
return p2;
}int main(void)
{
char *p1 = NULL;
char *p2 = NULL;p1 = GetChar1();
p2 = GetChar2();
//打印数据
printf("p1 = %s\n", p1);
printf("p2 = %s\n", p2);
//打印地址
printf("p1 = %5d\n", p1);
printf("p2 = %5d\n", p2);
system("pause");
}

在内存中表示为:

因为GetChar函数里面都是指针所以都放在栈区,而常量都在全局区。

当被调函数return之后,上面两个指针被释放,然后将地址赋给main函数里面的指针,他们就指向相应的值。

接下来,还有一个易错的点!!!

#include "stdio.h"char *GetChar1(void)
{
char *p1 = "abcdefg1";
return p1;
}char *GetChar2(void)
{
char *p2 = "abcdefg1";
return p2;
}int main(void)
{
char *p1 = NULL;
char *p2 = NULL;p1 = GetChar1();
p2 = GetChar2();
//打印数据
printf("p1 = %s\n", p1);
printf("p2 = %s\n", p2);
//打印地址
printf("p1 = %5d\n", p1);
printf("p2 = %5d\n", p2);
system("pause");
}

main函数里面指针地址是一样的

3.3 堆和栈例子

用户自己申明的变量是在堆中存放的,只有用户释放。

#include "stdio.h"char *GetString(int num)
{
char *s = NULL;
s = (char *)malloc(sizeof(char)*num);
if (s == NULL)
{
return NULL;
}
return s;
}
int main(void)
{
char *p1 = NULL;
p1 = GetString(10);
if (p1 == NULL)
{
return;
}
strcpy(p1, "abcdefg");
printf("%s\n", p1);
system("pause");
}

内存中分布:

当GetString()被调用后,s释放之后,malloc分配的空间还是存在,所以还能继续打印。

接下来的问题在实际写的过程中会犯错:

#include "stdio.h"char *GetString(int num)
{
char *s = NULL;
s = (char *)malloc(sizeof(char)*num);
if (s == NULL)
{
return NULL;
}
return s;
}char *GetString1(void)
{
char s1[10];
strcpy(s1, "qwerty");
printf("%s\n", s1);
return s1;
}
int main(void)
{
char *p1 = NULL;
char *p2 = NULL;
p1 = GetString(10);
if (p1 == NULL)
{
return;
}
p2 = GetString1();
strcpy(p1, "abcdefg");
printf("%s\n", p1);
printf("%s\n", p2);
system("pause");
}

这时的p2其实打印不出来或者程序死机了。这是因为GetString1()中的s1变量是申明在栈区中,当调用结束后,被释放了,那块区域中的qwerty就没了。但是地址还是那个10字节的起始地址,并没有全部return出来。

其他

内存中的栈是开口向下的。

版权声明:本文为CSDN博主「五道杠的小屁孩wwk」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_36101480/article/details/106181096


【END】更多精彩推荐
☞尤雨溪:重头来过的 Vue 3 带来了什么?
☞原来 Kylin 的增量构建,大有学问!| 原力计划
☞可怕!CPU 竟成了黑客的帮凶!
☞如何用NLP辅助投资分析?三大海外机构落地案例详解
☞这 10 个云计算错误,会让你的业务一蹶不振!
☞好扑科技结合区块链行业发展趋势,重磅推出“好扑区块链合伙人”计划
点击阅读原文,精彩继续。
你点的每个“在看”,我都认真当成了喜欢

抓住指针的精髓,才算掌握了 C 语言的灵魂!相关推荐

  1. 伪原创文章如何写才算高质量

    一.伪原创文章来源 伪原创文章来源可以有很多种方法,如果是产品使用保养类可以去百度知道搜索或者百度经验等,还可以去同行排名靠后的网站中获取,如果是发不到自己的网站内,尽量选择还没有被搜索引擎收录的为好 ...

  2. 短视频,究竟“多短”才算短?

    在线上网络江湖里,人们看见冒尖急流,而容易忽视底层的暗涌.移动互联网把"表达权下放"至每一个人,那些玩自媒体.直播.短视频的人,其专业水准可能不及记者.模特.演员,但他们够真实.放 ...

  3. 开宝箱怎么设计才算好?大脑说了算!

    开宝箱怎么设计才算好?大脑说了算! 策划运营 /  2014-10-24 /  Brain Intelligence 分享到: 1 本文是Brain Intelligence(布雷恩英咨询公司)给游戏 ...

  4. 精通python能干嘛-一个程序员怎样才算精通Python?

    原标题:一个程序员怎样才算精通Python? 作者:赖明星 我会先给出我对精通Python的理解,然后给出一些Python中有难度的知识点.如果大家在看完我这篇回答之前,已经充分理解了我列出的各个知识 ...

  5. 怎样才算熟悉python-终于找到python怎么才算入门

    为了提高模块加载的速度,每个模块都会在__pycache__文件夹中放置该模块的预编译模块,命名为module.version.pyc,version是模块的预编译版本编码,一般都包含Python的版 ...

  6. python工程师证书-一个程序员怎么才算精通python

    我会先给出我对精通Python的理解,然后给出一些Python中有难度的知识点.如果大家在看完我这篇回答之前,已经充分理解了我列出的各个知识点,那么,我相信你已经算是精通Python了.如果不能,我希 ...

  7. VR眼镜,怎样才算性感?

    怎样在一个工业设计还处于起步阶段的国家,做出一款令人惊艳的产品?令人伤感的一个问题,回答之前或许我们应该扪心自问,为什么中国现在的工业设计还处于起步阶段?我的答案是,请问在中国,工业设计可以卖到几块钱 ...

  8. 计算机硬盘容量分盘计算,硬盘怎么规划分区大小才算科学合理? | 我爱分享网...

    硬盘怎么规划分区大小才算科学合理?这个问题通常电脑小白都会问,虽然有些非小白可能知道怎么分,但是下面有些内容你也不一定知道哦!我们常见硬盘大小为120G.500G.1T,下面就以这三种来介绍硬盘分区大 ...

  9. java创建日程到期提醒_Mac用户必备日程时间管理器,有计划有效率的人生才算完美!...

    有计划的人,才会产生强大的行动力,才会充满激情的去工作,因为他知道下一步该做什么,目标明确的人,一定会成功,所以,有计划有效率的人生才算完美! 每天的日程安排的满满的,没有一款规划任务,提高效率的GT ...

最新文章

  1. python多态_多态是什么?为什么要使用多态?
  2. CSharp中的数组和ArrayList及List
  3. html网页的结构框架代码
  4. Pycharm取消双击shift出现搜索框
  5. java jvm参数获取_在java代码中获取JVM参数
  6. 2022年给正在创作的程序员的实用工具
  7. python人脸识别表情检测器(2):基本框架的制作
  8. 如何利用matlab做BP神经网络分析(包括利用matlab神经网络工具箱)
  9. 聚观早报 | 元旦机票预订量增长145%;小米集团副总裁崔宝秋离职
  10. 古诗三百首(html)
  11. duffing matlab,duffing方程matlab
  12. ionic3 教程(一)安装和配置 1
  13. 大学计算机课读书笔记,信息技术读书笔记
  14. 【C语言】算法学习·种类并查集
  15. 世上万事,不过是一懒二拖三不读书
  16. http中get/put/post区别
  17. 转贴一下 老婆日记
  18. 文华财经期货日内多空金叉波段彩带幅图指标公式,震荡区间决策预警信号指标公式
  19. 淘宝API接口 upload_img - 上传图片到淘宝
  20. 测试触控延时的软件,重点测试:触控屏响应时间_笔记本评测-中关村在线

热门文章

  1. bzoj 3242: [Noi2013]快餐店
  2. imToken 测评通关攻略
  3. java 中的 ThreadLocal
  4. 聚合数据接口,提供开放API
  5. AutoCAD ObjectARX(VC)开发基础与实例教程2014版光盘镜像
  6. Android图片缩放方法
  7. 第39天-进程 _1(2013.09.11)
  8. (转)Altera的几个常用的Synthesis attributes
  9. SQOOP 导出Hive数据到MySQL
  10. [论文阅读] Cross-layer feature pyramid network for salient object detection