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

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

0a1358df00e7acefa33622674b055775.png

学习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)公众号,免费获取学习教程资料、技术就业咨询

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值