写在前面的话:虽然这段代码中对于指针的使用是不正确的,但是我却在这个不正确的代码中发现了另一个错误,而且深感迷惑,所以打算将此博文推到首页,请各位帮忙回答个问题。

在项目中用到了以下一段代码,执行结果有点奇怪,还没有想明白为什么会这样子

是在网络编程中用到的,因为需要根据新加入的用户IP和已经存在的用户列表中的用户IP进行比对,来判定该用户是否已经存在,所以就使用了上述办法,但是执行结果出人意料,因为if(0 == strcmp(newIp, oldIp))这行代码永远为真,为什么呢?

自己就跟踪代码调试,结果当执行过第二个红线那一行之后,newIp的值也发生了改变,而且newIp和oldIp指向的地址是一样的,为什么这样子呢?

我的猜测是,由于inet_ntoa函数的执行过程会做一些我们不知道的事情,它的功能是将u_long的数据转换为字符串表示的点分十进制Ip地址,但是转换过之后这个Ip地址存储在哪里呢?我认为,它应该是开辟了一个存储空间来存放这个字符串,接着第二次执行这个函数的时候也是如此做的,而且使用的存储空间是同一个存储空间,所以才造成了现在这种情况。

于是我就修改了一下代码,给newIp分配一个存储空间,将inet_ntoa的结果放到这个存储空间中去,这样代码就按照自己的思路正确的执行了。下面是修改后的代码:

犯这样的错误,或许对于一个新手来说很正常,总的来说,还是使用指针的时候要小心,否则就会出现一些意料之外的诡异事件。。。

不过我还是有个小疑问,两次使用inet_ntoa结果得到的存储空间地址是相同的,这是个巧合还是必然会发生的呢?我的想法是调用这个函数,它会自动分配一个空间来存储,但是立刻就销毁了,而值还存在那里,第二次使用还是随机分配,地址相同只不过是因为分配空间的算法认为刚才那个空间是可用的,所以就将此空间又分配给它了,所以,我认为这是个巧合,如果两个函数离的比较远,也就是说它们之间还有别的函数需要动态分配空间,那么它们的值就不会一样了。

下面是两次的执行结果:

事实胜于雄辩,看着调试的代码,我发现自己的猜测是错的,我在两次函数调用中间利用new分配了一块存储空间,结果p1和p2的值还是一样的。我迷惑了,难道这个函数每次都用一样的地址么?不可能吧。。。

于是我继续做下面的测试,在另外一个函数中使用该函数inet_ntoa,执行结果如下:

第一个函数中:

第二个函数中:

好吧,看到它们的地址,我彻底的迷惑了,我的猜测确实是错的,可是还是那个问题,为什么这个函数每次执行分配的存储空间都一样呢?

虽然还是带着自己的疑问结束了这个博客,但是也学到了很多的东西,遇到问题按着自己的思路去思考就好了,没必要一遇到问题就上网上搜去,当然我也不反对上网找资料,但是现在的现象是往往很多问题在网上都是重复的,搜来搜去都是一样,从这个网站转到另一个网站,而且这样的答案对自己的问题还没有什么价值。

我认为遇到问题,首先应该自己去思考解决思路,不要怕困难,其实当你真正的去做的时候才会发现并不是那么困难,而且这样更可以增加自己技术的增长,怎么说呢,我认为抄来的东西还是没有自己琢磨出来的知识让自己印象更深刻。

后面这段话可能不太符合某些人的观点,那么请保持绅士风度,因为我们应该让我们听到不同的声音,这样我们才能知道跟自己不同的观点。

谢谢这评论中两位的回答,我总结以下问题的答案,就是这个函数会把执行结果放在一个静态存储区,它保证在同一线程中下一次执行Socket函数之前,数据是有效的,所以,我们应该在下次执行Socket函数之前将数据拷贝出来。这里我只是保存了它的指针,所以,在下次执行此函数时,数据被覆盖了。

详见百度百科:inet_ntoa()

图片:

又谈C++指针(1)的更多相关文章

  1. Objective-C 再谈OC指针,对比C++/Java/Swift

    1.Objective-C的指针 OC一直是人感觉比较变态的一门语言,为什么呢?因为它的每个变量都是指针型,多的都几乎让人忘了那个*的存在了. 比如我定义了一个Student的Class,new了st ...

  2. 【洛谷日报#75】浅谈C++指针

    放入我的博客食用效果更佳(有很多oi学习资料) 1.指针基础 1.引用 C++有一个东西叫引用,引用相当于给对象(如:变量)起了另一个名字,引用必须用对象初始化,一旦初始化,引用就会和初始化其的对象绑 ...

  3. [转]浅谈C++指针直接调用类成员函数

    找了一番之后发现这篇文章讲的很清楚. 传送门

  4. 转:浅谈C/C++中的指针和数组(一)

    再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...

  5. (转) 谈C/C++指针精髓

    原文:http://www.cnblogs.com/madengwei/archive/2008/02/18/1072410.html   [摘要]    指针是C和C++语言编程中最重要的概念之一, ...

  6. 浅谈C中的指针和数组(一)

    本文转载地址:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242138.html 在原文的基础上加入自己的想法作为修改. 指针是C/C ...

  7. node c++多线程插件 第二天 c++指针

    虽然取名叫node多线程插件,但是目前还是在学习c++的情况. 今天谈一谈c++指针. c++指针就像是c#中的引用变量,例如一个Person类的实例zs{Name="张三",Ag ...

  8. C语言复习---二维数组和二级指针的关系:没关系,别瞎想(重点)

    前提:一维数组和一维指针为什么可以替换使用? ] = { , , }; int *p = a; ; i < ; i++) printf("%d ", *(p + i)); 上 ...

  9. 浅谈 C 语言中模块化设计的范式

    今天继续谈模块化的问题.这个想慢慢写成个系列,但是不一定连续写.基本是想起来了,就整理点思路出来.主要还是为以后集中整理做点铺垫. 我们都知道,层次分明的代码最容易维护.你可以轻易的换掉某个层次上的某 ...

随机推荐

  1. codeforces Epic Game 题解

    Simon and Antisimon play a game. Initially each player receives one fixed positive integer that does ...

  2. 批处理文件:将目录下所有的jar文件都加到CLASSPATH

    简便写法如下: 代码 : @echo off SetLocal EnableDelayedExpansion FOR %%i IN ("XXX\lib\*.jar") DO SET ...

  3. java装箱拆箱

    基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象的时候,我们会这样: Class a = new Class(p ...

  4. Linux对包管理阐述

    Centos/Redhat/Fedora的软件包,都是rpm后缀的文件.包管理器rpm(Redhat packages manager)  linux的哲学思想是简单命令解决复杂任务,因此每个软件的功 ...

  5. Synchronized和Lock, 以及自旋锁 Spin Lock, Ticket Spin Lock, MCS Spin Lock, CLH Spin Lock

    Synchronized和Lock synchronized是一个关键字, Lock是一个接口, 对应有多种实现. 使用synchronized进行同步和使用Lock进行同步的区别 使用synchro ...

  6. IT忍者神龟之 oracle行转列、列转行

    一.行转列 须要将例如以下格式 转换为: 这就是最常见的行转列,主要原理是利用decode函数.聚集函数(sum).结合group by分组实现的 create table test( id varc ...

  7. PHP中的一些安全配置

    PHP中的配置至关重要,包含php.ini的配置,还有系统权限的配置,一下是我总结的一些配置 一.PHP的模块 ./configure \ --with-libdir=lib64 \ --prefix ...

  8. WordPress网站搬家的问题

    老邢的博客搬家全过程(wordpress搬家知识总结)   网站搬家过程中的几个问题   WordPress网站搬家的方法   WORDPRESS.ORG - zh-cn:WordPress 博客搬家 ...

  9. 用一个URL加一个JAVA壳做成一个安卓应用

    若想获得更新版本欢迎加入我们的 “本地应用开发webapp"群,一起协力开发一处编写处处运行的“本地应用”.我们将一直开源,将智慧共享,只有这样我们才能一起将应用体验做好! 特点: 1.程序 ...

  10. Linux使用技巧5--格式化U盘

    通常来说,格式化一个分区的U盘还是非常easy的.仅仅须要使用mkfs命令指定目标文件系统就能够了,样例例如以下: $ sudo fdisk -l $ sudo mkfs -t vfat /dev/s ...