C语言/C++从入门到精通之指针易错点总结
小职 2021-01-22 来源 :https://blog.csdn.net/weixin_36101480/article/deta 阅读 769 评论 0

摘要:指针是C语言的灵魂,所以学好指针很关键,本篇主要介绍了C语言/C++从入门到精通之指针易错点总结,通过具体的内容向大家展现,希望对大家C语言/C++的学习有所帮助。

指针是C语言的灵魂,所以学好指针很关键,本篇主要介绍了C语言/C++从入门到精通之指针易错点总结,通过具体的内容向大家展现,希望对大家C语言/C++的学习有所帮助。

C语言/C++从入门到精通之指针易错点总结


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



1、数组传参和数组形参

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。


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



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

#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、变量在内存中的位置

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


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出来。



4、其他

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



关注“职坐标在线”(Zhizuobiao_Online)公众号,免费获取学习教程资料、技术就业咨询

C语言/C++从入门到精通之指针易错点总结

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程