指针步长要注意
eg1:
#include <stdio.h> int main(void) { int *s = (int *)"believe yourself!"; s++; printf("%c",*(char *)s); return 0; }
输出:
int四字节,char一字节。注意步长。
有了上面的铺垫,我们来看下一个,这是一个面试题:
找出下面代码的bug:
#include <stdio.h>
void test_func(int * p)
{
/*do somethings*/
printf("%d\n",*p);
}
int main(void)
{
char a=1;
test_func(&a);
return 0;
}
当然,很明显的是char * 和 int *的类型不兼容,虽然C语言中的char就是int的子集,但是在指针操作的时候,类型所占用字节是极其重要的。
不过,这并不代表这个题目就结束了,你要找出问题的根源,我们试试下面这样强制类型转换:
#include <stdio.h>
void test_func(int * p)
{
/*do somethings*/
printf("%d\n",*p);
}
int main(void)
{
char a=1;
test_func((int *)&a);
return 0;
}
这样编译倒是没有警告了,但是运行呢?
明显不对,我们再试试多运行几次呢?
居然每次运行的结果都不一样,这是什么导致的呢?
有了第一个例子的启发,我们应该能够明白一点什么,char和int数据是不一样的字节大小,而指针操作和对象所占字节有着关系,本来是一个char类型数据的地址,你把它给一个int *的指针,那么这个int类型的指针,会按照四个字节去解读这个char类型的指针,这样的出来数据,发生错误是意料之中的。所以,我们使用指针操作的时候,一定要谨慎、细致、缜密、灵活。
那怎么修改呢?
我们可以这样:
#include <stdio.h> void test_func(int * p) { /*do somethings*/ printf("%d\n",(char)*p); } int main(void) { char a=12; //printf("%p %p \n",&a,(int *)&a); test_func((int *)&a); return 0; }
可以看到无论怎么运行结果都是正确的。你可能会想,哪有这样的操作,这样的强制类型转换在链表之中我相信应该经常看到吧,还有一个解决办法就是实参和形参完全匹配,这也是最规范的方法。不过往往很多时候,我们都需要强制类型转换,尤其涉及void *的类型,在上面的例子中,推荐使用实参和形参指针类型完全匹配,而在void *的应用中,强制类型转换是一大利器。
欢迎加入作者的小圈子
扫描下方左边二维码加入QQ交流群,扫描下方右边二维码关注个人微信公众号并获取更多隐藏干货,QQ交流群:816747642 微信公众号:Crystal软件学堂
作者:Crystal软件学堂 bilibili视频教程地址:https://space.bilibili.com/5782182 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在转载文章页面给出原文连接。 如果你觉得文章对你有所帮助,烦请点个推荐,你的支持是我更文的动力。 文中若有错误,请您务必指出,感谢给予我建议并让我提高的你。 |