C语言指针专题——使用指针要注意这些
本文为原创,欢迎转发:
欢迎关注微博与微信号:C语言编程技术分享
C语言中,指针的概念有点难懂,使用起来稍微不注意,也会遇到各种问题。在本文中,我列举出了几个使用指针不当的方式,希望朋友们在编程实践中也多多注意。
一、野指针
野指针这个东东是经常被人提及的,其危害也是大家有目共睹的。我很早之前写过一篇文章来说明野指针的,链接是:
有兴趣的朋友可以看看,这里就不多废话了!
二、越界访问
越界访问最常见的就是使用指针访问数组元素了。比如下面这段代码:
#include <stdio.h> int main(void)
{
int number[3] = {1, 2, 3};
int *p = NULL; p = number; for(int index = 0;index < 4; index++)
{
printf("%d\n", *(p + index));
} return 0;
}
代码很好理解,就是用一个指针p,逐个访问数组的每个元素,并打印出来。
当index为3的时候,p + index此时就越出数组的长度了,那么*(p + index)访问的就是数组以外的内容,输出啥呢?看下面的输出结果:
最后一个数字,是2293468,这是数组以外的元素。
本例中还好,对数组以外的内容只是读取一下而已,如果是写操作的话,会发生什么,看你的人品了!
三、指针不可相加
两个指针相加,你见过吗?相乘呢?看下面的代码:
#include <stdio.h> int main(void)
{
int number[3] = {1, 2, 3};
int *p = NULL, *q = NULL; p = number;
q = &number[2]; printf("%d\n", p + q); return 0;
}
我运行了下,报了一个错:
先不去管这个错误,我们可以自己想想,两个指针相加,有什么意义呢?指针的值,也是一个数字,只不过这个数字是别人的一个地址,两个指针相加,就是两个地址值相加,确实没啥意义!
但是如果两个指针相减呢?如代码中指针q减去指针p,这个就是有意义了,意义就在于两个指针相隔几个int型元素。有兴趣的朋友可以改下代码看看。
四、多个指针指向同一个常量区域
先上代码:
#include <stdio.h> int main(void)
{
const char *p = "12345";
const char *q = "12345";
const char *r = "123456"; printf("%d\n", (p == q));
printf("%d\n", (p == r)); return 0;
}
运行下:
从结果中可以看到,指针p与q的值是一样的,也就是说,指针p与指针q是指向同一个字符串“12345”,而指针p与指针r就各自指向各自的字符串了。
对于常量字符串“12345”而言,在程序期间,只有自己这一个实体,没有其它的拷贝,指针p和指针q都指向它,这样设计可以节约存储空间。
五、小心sizeof(指针)的用法
关于sizeof(指针),计算的是指针变量本身占用的字节数,认识不到这一点,就会闹出笑话,比如下面的程序:
#include <stdio.h> void print(int number[])
{
for(int index = 0;index < sizeof(number) / sizeof(number[0]); index++)
{
printf("%d\n", number[index]);
}
} int main(void)
{
int number[3] = {1, 2, 3};
int *p = NULL; p = number; print(p); return 0;
}
在函数print中,原意是希望通过“sizeof(number) / sizeof(number[0])”来计算出数组的大小,来一个一个输出数组的元素。可实际上呢,根本不是。运行结果如下:
结果只输出了一个元素。
函数print的形参number虽然写的是数组的形式,但是实际上它是一个指针,
sizeof(number) 计算的是指针本身占用的字节数,为4;
sizeof(number[0])计算的是int整型变量占用的字节数,也为4;
因此for循环只循环了一次就结束了。
我曾经也写过一篇文章,来讲解sizeof(数组)和sizeof(指针)的区别,有兴趣的朋友可以看看:
别混淆了sizeof(数组名)和sizeof(指针) - 知乎专栏
C语言指针专题——使用指针要注意这些的更多相关文章
- 指针专题6-空指针NULL和void指针
1 NULL指针 一个指针变量可以指向计算机中任何一块内存,不管该内存有没有被分配,也不管该内存有没有使用权限,只要把地址给他,他就可以指向.C语言没有一种机制保证指向内存的正确性,程序员必须自己提高 ...
- C语言指针专题——序
看到好多的C语言初学者学到指针时,都觉得指针怎么那么难啊!我也想起了我当时学习指针时遇到的困难,确实很难!到底是教程写的不好呢,还是老师教的不好呢?我觉得都有. 网上搜索指针讲解的资料很多,我也看了不 ...
- C语言指针专题——指针难学的4点原因
前一篇跟大家聊了聊指针的概念,可是就算了解了指针是什么,为什么依然感觉难学?我试着从几个点切入,聊聊指针难学之处. 文末会给大家推荐几本书,有需要的朋友可以看看! 难点1. 讨厌的星号 定义指针变量p ...
- Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针
Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针 1.1. java方法引用(Method References) 与c#委托与脚本语言js ...
- C#委托与C语言函数指针及函数指针数组
C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...
- 【C语言】14-返回指针的函数与指向函数的指针
前言 前面我们花了接近3个章节学习指针,应该都感受到指针的强大了吧.指针可以根据地址直接操作内存中的数据,使用得当的话,不仅能使代码量变少,还能优化内存管理.提升程序性能.关于指针的内容还非常多,比如 ...
- 【转载】C/C++语言void及void指针深层探索
C/C++语言void及void指针深层探索 1.概述许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误.本文将对void关键字的深刻含义进行解说,并详述vo ...
- C语言函数指针变量和指针函数以及指针数组
C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址.我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数.然后通过指针变量就可以找到并调用这 ...
- C语言复杂的函数指针声明
复习C语言ING,发现复杂的函数指针声明看不懂,百度半天终于略知一二. 讲的比较详细的一篇blog: http://blog.csdn.net/megaboy/article/details/4827 ...
随机推荐
- DevExpress的xtraMessageBox汉化
原文:DevExpress的xtraMessageBox汉化 项目使用的界面库是DevExpress 相当好用,不过里面弹出对话框XtraMessageBox的按钮都是英文的, 可能会对用户造成困扰, ...
- WPF WindowChrome 自定义窗口
1.wpf自定义窗口: WindowChrome类描述:https://msdn.microsoft.com/zh-cn/library/system.windows.shell.windowchro ...
- C# ToolStrip在父窗体失去焦点时,点击里面的按钮无效
C#里面ToolStrip控件,在父窗体失去焦点的情况下,第一次点击ToolStrip上面的按钮,只是让父窗体获得焦点,并不会引发按钮的Click事件.要执行按钮操作必须再点击一次.相当于说,在父窗体 ...
- oracle 使用db_link 导入导出小结
客户有一个需求,是将一个库中的某个用户迁移到一台新的oracle服务器上,因数据量较小,并且不涉及版本的升级,所以可以采用创建一个dblink,然后通过这个dblink直接从源库将用户数据导出并导入到 ...
- C#try catch块
try..catch块的出现是为了异常处理. 格式为:try{...可能发生异常的代码...} catch{...对异常的处理...} finaly{...无论如何都会执行的代码..} 上面的只是一般 ...
- 轻量级 Material Design 前端框架 MDUI (纯html,css,与css框架跟react vue不冲突)
MDUI 是一个轻量级的 Material Design 前端框架,对照着 Material Design 文档进行开发,争取 1:1 实现 Material Design 中的组件. 多主题支持 M ...
- xe5 for android 地理定位GPS
先上源码,在解释. implementation uses androidapi.jni.JavaTypes, androidapi.jni.Location, FMX.helpers.android ...
- Codility---Dominator
Task description A zero-indexed array A consisting of N integers is given. The dominator of array A ...
- .NET中生成水印更好的方法
.NET中生成水印更好的方法 为了保护知识产权,防止资源被盗用,水印在博客.网店等场景中非常常见. 本文首先演示了基于System.Drawing.Image做正常操作.然后基于Direct2D/WI ...
- JAVA8之lambda表达式详解
原文:http://blog.csdn.net/jinzhencs/article/details/50748202 lambda表达式详解 一.问题 1.什么是lambda表达式? 2.lambda ...