﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-I believe I can make a miracle-随笔分类-我的技术文摘</title><link>http://www.cnitblog.com/wujian-IT/category/6353.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 10 Oct 2011 22:26:13 GMT</lastBuildDate><pubDate>Mon, 10 Oct 2011 22:26:13 GMT</pubDate><ttl>60</ttl><item><title>预编译指令的作用</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/11/11/36148.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Sun, 11 Nov 2007 14:20:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/11/11/36148.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/36148.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/11/11/36148.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/36148.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/36148.html</trackback:ping><description><![CDATA[预编译一般用来防止头文件的重复包含和编译。<br><br>在我们用C做开发的是候，有时候项目很大，我们所编写的程序会很长。这样我们如果还是写在一个文件中会出现管理上的问题和&nbsp;<br>查看上的不方便。因此，我们可以分多个文件编写我们的程序，这样把一个功能的程序写到一个文件里，便于查看&nbsp;也有助于我们管理。&nbsp;<br>如main.c&nbsp;sd.h&nbsp;sd.c&nbsp;lcd.h&nbsp;lcd.c&nbsp;fat.h&nbsp;fat.c&nbsp;delay.h&nbsp;delay.c&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;至于头文件(sd.h)和源文件(sd.c)的写法应该是这样的：&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在头文件中&nbsp;我们写的是&nbsp;函数的声明，和一些使用到的变量的声明；&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在源文件中&nbsp;我们写的是&nbsp;对应于头文件中的函数的具体实现，即函数左大括号和右大括号中的内容。&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;在具体使用相关函数是可以使用#include&nbsp;命令来包含其函数所在的头文件。下面我们虚拟如下的一个程序结构来展开说明：&nbsp;<br><br>如在main.c中&nbsp;<br>#include&nbsp;delay.h&nbsp;<br>#include&nbsp;sd.h&nbsp;<br>#include&nbsp;lcd.h&nbsp;<br>#include&nbsp;fat.h&nbsp;<br>main()&nbsp;<br>{&nbsp;<br>&nbsp;&nbsp;sd_init();&nbsp;<br>&nbsp;&nbsp;delay_nms(10);&nbsp;<br>&nbsp;&nbsp;lcd_init();&nbsp;<br>&nbsp;&nbsp;while(1)&nbsp;<br>&nbsp;&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;....&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;....;&nbsp;<br>&nbsp;&nbsp;}&nbsp;<br>}&nbsp;<br><br>在sd.c中&nbsp;<br>void&nbsp;sd_init()&nbsp;<br>{&nbsp;<br>&nbsp;......&nbsp;<br>&nbsp;......;&nbsp;&nbsp;<br>}&nbsp;<br><br>在sd.h中&nbsp;<br>#include&nbsp;delay.h&nbsp;<br>#include&nbsp;.......&nbsp;<br>void&nbsp;sd_init()；&nbsp;<br>.....&nbsp;<br><br>在delay.c中&nbsp;<br>void&nbsp;delay_nms(UINT&nbsp;n)&nbsp;<br>{&nbsp;<br>&nbsp;for(....)&nbsp;<br>&nbsp;&nbsp;{...&nbsp;<br>&nbsp;&nbsp;&nbsp;_asm_("nop");&nbsp;<br>&nbsp;&nbsp;&nbsp;...&nbsp;<br>&nbsp;&nbsp;}&nbsp;&nbsp;<br><br>}&nbsp;<br>在delay.h中&nbsp;<br>void&nbsp;delay_nms(UINT&nbsp;n);&nbsp;<br><br>.....&nbsp;<br><br>&nbsp;&nbsp;&nbsp;我们看，如果在头文件的书写中都没加预编译指令&nbsp;<br>#ifndef&nbsp;XXXXXXXX&nbsp;&nbsp;<br>#define&nbsp;XXXXXXXX&nbsp;<br>&nbsp;&nbsp;....&nbsp;<br>&nbsp;&nbsp;....&nbsp;<br>&nbsp;&nbsp;（头文件内容）&nbsp;<br>&nbsp;&nbsp;....&nbsp;<br>#endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br><br><br>会出现怎么样的情况？？？？&nbsp;&nbsp;&nbsp;&nbsp;其实这样，编译会报错。编译器会提示&nbsp;void&nbsp;delay_nms()定义了两次。为什么会出现这种情况呢？&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;我们顺着程序读一下，当我们在main.c中，编译器读到#include&nbsp;delay.h时会把&nbsp;delay.h文件中的内容包含进来，这样delay.h中的&nbsp;<br>delay_nms()函数定义了一次，当我们在往下，读到#include&nbsp;sd.h时，把sd.h包含进来，在把sd.h的内容展开，我们又读到了一次delay.h&nbsp;<br>这样又把delay.h的内容包含近了main.c&nbsp;。因此，我们发现delay.h被main.c重复包含了2次。这样使得void&nbsp;delay_nms()函数也被定义了二次。&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;如何解决重复定义的问题，我们是用条件编译，#ifndef&nbsp;..等。在头文件中加入条件编译指令，如下：&nbsp;<br><br>在sd.h中&nbsp;<br>#ifndef&nbsp;_SD_H_&nbsp;&nbsp;<br>#define&nbsp;_SD_H_&nbsp;<br><br>#include&nbsp;delay.h&nbsp;<br>#include&nbsp;.......&nbsp;<br>void&nbsp;sd_init()；&nbsp;<br>.....&nbsp;<br><br>#endif&nbsp;<br><br>在delay.h中&nbsp;<br>#ifndef&nbsp;_DELAY_H_&nbsp;&nbsp;<br>#define&nbsp;_DELAY_H_&nbsp;<br><br>void&nbsp;delay_nms(UINT&nbsp;n);&nbsp;<br><br>.....&nbsp;<br>#endif&nbsp;<br><br>&nbsp;&nbsp;&nbsp;这样，让我们再看下会出现什么情况。&nbsp;<br>&nbsp;&nbsp;&nbsp;当我们在main.c中，编译器读到#include&nbsp;delay.h时会把&nbsp;delay.h文件中的内容包含进来，（#ifndef&nbsp;_DELAY_H_）我们先判断有没有定义&nbsp;<br>了&nbsp;_DELAY_H_&nbsp;&nbsp;这个宏，由于这是第一次调用delay.h，_DELAY_H_这个宏还没定义，这样编译器会顺序向下执行，执行到#define&nbsp;_DELAY_H_&nbsp;<br>则定义了一个_DELAY_H_宏，宏值为NULL.&nbsp;当我们main.c中再往下，读到#include&nbsp;sd.h时，把sd.h包含进来，在把sd.h的内容展开，&nbsp;<br>我们又读到了一次delay.h。&nbsp;这一次&nbsp;我们判断&nbsp;#ifndef&nbsp;_DELAY_H_&nbsp;结果是已经定义了，这样，编译器会跳过下面的内容，直接到&nbsp;#endif。&nbsp;<br>可见，我们的函数&nbsp;void&nbsp;delay_nms(UINT&nbsp;n);&nbsp;就不会被重复定义二次！&nbsp;对于其他的头文件，我们现在也加上&nbsp;预编译指令，防止被重复包含。&nbsp;<br><br>&nbsp;&nbsp;另外，在WinAVR中，如果使用多文件编译，需要在Makeflie中修改&nbsp;SRC&nbsp;=&nbsp;$(TARGET).c&nbsp;在其后面添加你的头文件的源文件的名字。如&nbsp;<br>&nbsp;&nbsp;SRC&nbsp;=&nbsp;$(TARGET).c&nbsp;delay.c&nbsp;sd.c&nbsp;fat.c&nbsp;lcd.h&nbsp;<br><br><br><br><br>希望以上内容能对初学者有所帮助，有什么不对的地方也恳请大家指出修正。
<br><img src ="http://www.cnitblog.com/wujian-IT/aggbug/36148.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-11-11 22:20 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/11/11/36148.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>_init宏</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/11/06/35950.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Tue, 06 Nov 2007 10:36:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/11/06/35950.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/35950.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/11/06/35950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/35950.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/35950.html</trackback:ping><description><![CDATA[<div class=t_msgfont id=message5229490>_init关键字不是gcc的， 而是linux内核的。&nbsp;&nbsp;__init， __initdata等属性标志， 是要把这种属性的代码放入目标文件的.init.text节， 数据放入.init.data节──这一过程是通过编译内核时为相关目标平台提供了xxx.lds链接脚本， 来指导ld完成的。 对i386来说， 可以参考arch/i386/kernel/vmlinux.lds.S文件。<br><br>对编译成module的代码和数据来说， 当模块加载时， __init属性的函数就被执行;<br>对静态编入内核的代码和数据来说， 当内核引导时， do_basic_setup()函数调用do_initcalls()函数， 后者负责所有.init节函数的执行。<br><br>
<div class=t_msgfont id=message5230488>__init说明这个函数仅在初始化的时候使用,在模块挂载以后,就会把初始化函数扔掉,可以把该函数占用的内存扔掉,</div>
<br></div>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/35950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-11-06 18:36 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/11/06/35950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>原码、反码和补码</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/23/35248.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Tue, 23 Oct 2007 15:11:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/23/35248.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/35248.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/23/35248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/35248.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/35248.html</trackback:ping><description><![CDATA[<p>大家都知道数据在计算机中都是按字节来储存了，1个字节等于8位（1Byte=8bit），而计算机只能识别0和1这两个数，所以根据排列，1个字
节能代表256种不同的信息，即28（0和1两种可能，8位排列），比如定义一个字节大小的无符号整数（unsigned
char），那么它能表示的是0～255（0~28-1）这些数，一共是256个数，因为，前面说了，一个字节只能表示256种不同的信息。别停下，还是
一个字节的无符号整数，我们来进一步剖析它，0是这些数中最小的一个，我们先假设它在计算机内部就用8位二进制表示为00000000（从理论上来说也可
以表示成其他不同的二进制码，只要这256个数每个数对应的二进制码都不相同就可以了），再假设1表示为00000001，2表示为00000010，3
表示为00000011，依次类推，那么最大的那个数255在8位二进制中就表示为最大的数11111111，然后，我们把这些二进制码换算成十进制看
看，会发现刚好和我们假设的数是相同的，而事实上，在计算机中，无符号的整数就是按这个原理来储存的，所以告诉你一个无符号的整数的二进制码，你就可以知
道这个数是多少，而且知道在计算机中，这个数本身就是以这个二进制码来储存的。比如我给你一个2个字节大小的二进制码，首先声明它表示的是无符号的整数：
00000000
00000010，我们把前面的0省略，换算一下，它表示的也是数值2，和前面不同的是，它占了2个字节的内存。不同的类型占的内存空间不同，如在我的电
脑中char是1个字节，int是4个字节，long是8个字节（你的可能不同，这取决于不同的计算机设置），它们的不同之处仅仅是内存大的能表示的不同
的信息多些，也就是能表示的数范围更大些（unsigned
int能表示的范围是0~28*4-1），至于怎么算，其实都是一样的，直接把二进制与十进制相互转换，二进制就是它在计算机中的样子，十进制就是我们所
表示的数。啊哈，原来这些都是可以计算的呀，我曾经还以为不同的计算机储存的原理是不同的，取决于商家的喜好呢，呵呵。说了这么多怎么还没有提到原码、反
码和补码呀，别急别急，心急吃不了热豆腐，呵呵，因为无符号的整数根本就没有原码、反码和补码。（啊，那不是被欺骗了，5555````我告诉妈妈去，哥
哥欺负我）都说了别急嘛，你就不想想我说了这么半天的无符号整数，那么有符号的整数怎么办啊？</p>
<p>　　呵呵，对，只有有符号的整数才有原码、反
码和补码的！其他的类型一概没有。虽然我们也可以用二进制中最小的数去对应最小的负数，最大的也相对应，但是那样不科学，下面来说说科学的方法。还是说一
个字节的整数，不过这次是有符号的啦，1个字节它不管怎么样还是只能表示256个数，因为有符号所以我们就把它表示成范围：-128-127。它在计算机
中是怎么储存的呢？可以这样理解，用最高位表示符号位，如果是0表示正数，如果是1表示负数，剩下的7位用来储存数的绝对值的话，能表示27个数的绝对
值，再考虑正负两种情况，27*2还是256个数。首先定义0在计算机中储存为00000000，对于正数我们依然可以像无符号数那样换算，从
00000001到01111111依次表示1到127。那么这些数对应的二进制码就是这些数的原码。到这里很多人就会想，那负数是不是从
10000001到11111111依次表示-1到-127，那你发现没有，如果这样的话那么一共就只有255个数了，因为10000000的情况没有考
虑在内。实际上，10000000在计算机中表示最小的负整数，就是这里的-128，而且实际上并不是从10000001到11111111依次表示-1
到-127，而是刚好相反的，从10000001到11111111依次表示-127到-1。负整数在计算机中是以补码形式储存的，补码是怎么样表示的
呢，这里还要引入另一个概念——反码，所谓反码就是把负数的原码（负数的原码和和它的绝对值所对应的原码相同，简单的说就是绝对值相同的数原码相同）各个
位按位取反，是1就换成0，是0就换成1，如-1的原码是00000001，和1的原码相同，那么-1的反码就是11111110，而补码就是在反码的基
础上加1，即-1的补码是11111110+1=11111111，因此我们可以算出-1在计算机中是按11111111储存的。总结一下，计算机储存有
符号的整数时，是用该整数的补码进行储存的，0的原码、补码都是0，正数的原码、补码可以特殊理解为相同，负数的补码是它的反码加1。下面再多举几个例
子，来帮助大家理解！</p>
<p>十进制　&#8594;　二进制　　（怎么算？要是不知道看计算机基础的书去）<br>47　　　&#8594;　101111</p>
<p>有符号的整数　　　　原码　　　　反码　　　　补码<br>　　47　　　　　　00101111　　11010000　　00101111（正数补码和原码相同）<br>　－47　　　　　　00101111　　11010000　　11010001（负数补码是在反码上加1）</p>
<p>再举个例子，学C语言的同学应该做过这道题：<br>把－1以无符号的类型输出，得什么结果？（程序如下）</p>
<p>#include&lt;iostream.h&gt;<br>void main()<br>{<br>&nbsp;short int  n=-1;<br>&nbsp;cout&lt;&lt;(unsigned short int)n&lt;&lt;endl;<br>}</p>
<p>
首先在我的电脑中short
int类型的储存空间是2个字节，你的可能不同，我说过，这取决于你的计算机配置。它能储存28*2＝65536个不同的数据信息，如果是无符号那么它的
范围是0~65535（0~216-1），如果是有符号，那么它的范围是-32768~32767（-215~215-1）。这道题目中，开始n是一个有
符号的短整型变量，我们给它赋值为-1，根据我们前面所说的，它在计算机中是以补码11111111
11111111储存的，注意前面说了是2个字节。如果把它强制为无符号的短整型输出的话，那么我们就把刚才的二进制把看成无符号的整型在计算机中储存的
形式，对待无符号的整型就没有什么原码、反码和补码的概念了，直接把11111111
11111111转化成十进制就是65535，其实我们一看都是一就知道它是范围中最大的一个数了。呵呵，就这么简单。你个把上面的源代码编译运行看看，
如果你的电脑short int也是两个字节，那就会和我得一样的结果。你可以先用这个语句看看：cout&lt;&lt;sizeof(short
int)&lt;&lt;endl;看看你的电脑里的短整型占多少的储存空间，也可以用sizeof来看其它任何类型所分配的储存空间。</p>
<p>　　最后提醒一句，关于数据如何在计算机中储存的，这里只适用于整型的数据，对于浮点型的是另一种方式，这里我们暂时就不深究了。</p>
<br><img src ="http://www.cnitblog.com/wujian-IT/aggbug/35248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-23 23:11 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/23/35248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>内存分配方式</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34894.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Mon, 15 Oct 2007 10:13:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34894.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34894.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34894.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34894.html</trackback:ping><description><![CDATA[<p>内存分配方式有三种：</p>
<p>（1）从静态存储区域分配。内存在程序编译的时候就已经分配好，这块内存在程序的整个运行期间都存在。例如全局变量，static变量。</p>
<p>（2）在栈上创建。在执行函数时，函数内局部变量的存储单元都可以在栈上创建，函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中，效率很高，但是分配的内存容量有限。</p>
<p>（3）从堆上分配，亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存，程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定，使用非常灵活，但问题也最多。</p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-15 18:13 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>malloc/free 与 new/delete 的区别</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34893.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Mon, 15 Oct 2007 10:11:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34893.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34893.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34893.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34893.html</trackback:ping><description><![CDATA[<p>有了malloc/free 为什么还要new/delete ？<br>malloc 与free 是C++/C 语言的标准库函数，new/delete 是C++的运算符。它们都可<br>用于申请动态内存和释放内存。<br>对于非内部数据类型的对象而言，光用maloc/free 无法满足动态对象的要求。对象<br>在创建的同时要自动执行构造函数， 对象在消亡之前要自动执行析构函数。由于<br>malloc/free 是库函数而不是运算符，不在编译器控制权限之内，不能够把执行构造函数<br>和析构函数的任务强加于malloc/free。<br>因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new，以及一个<br>能完成清理与释放内存工作的运算符delete。注意new/delete 不是库函数。<br>我们先看一看malloc/free 和new/delete 如何实现对象的动态内存管理，见示例7-8。<br>class Obj<br>{<br>public :<br>Obj(void){ cout &lt;&lt; &#8220;Initialization&#8221; &lt;&lt; endl; }<br>~Obj(void){ cout &lt;&lt; &#8220;Destroy&#8221; &lt;&lt; endl; }<br>void Initialize(void){ cout &lt;&lt; &#8220;Initialization&#8221; &lt;&lt; endl; }<br>void Destroy(void){ cout &lt;&lt; &#8220;Destroy&#8221; &lt;&lt; endl; }<br>};<br>void UseMallocFree(void)<br>{<br>Obj *a = (obj *)malloc(sizeof(obj)); // 申请动态内存<br>a-&gt;Initialize(); // 初始化<br>//&#8230;<br>a-&gt;Destroy(); // 清除工作<br>free(a); // 释放内存<br>}<br>void UseNewDelete(void)<br>{<br>Obj *a = new Obj; // 申请动态内存并且初始化<br>//&#8230;<br>delete a; // 清除并且释放内存<br>}<br>示例7-8 用malloc/free 和new/delete 如何实现对象的动态内存管理<br>类Obj 的函数Initialize 模拟了构造函数的功能，函数Destroy 模拟了析构函数的功<br>能。函数UseMallocFree 中，由于malloc/free 不能执行构造函数与析构函数，必须调用<br>成员函数Initialize 和Destroy 来完成初始化与清除工作。函数UseNewDelete 则简单得</p>
<p>多。<br>所以我们不要企图用malloc/free 来完成动态对象的内存管理，应该用new/delete。<br>由于内部数据类型的&#8220; 对象&#8221;没有构造与析构的过程，对它们而言malloc/free 和<br>new/delete 是等价的。<br>既然new/delete 的功能完全覆盖了malloc/free，为什么C++不把malloc/free 淘<br>汰出局呢？这是因为C++程序经常要调用C 函数，而C 程序只能用malloc/free 管理动<br>态内存。<br>如果用free 释放&#8220;new 创建的动态对象&#8221;，那么该对象因无法执行析构函数而可能<br>导致程序出错。如果用delete 释放&#8220;malloc 申请的动态内存&#8221;，理论上讲程序不会出错，<br>但是该程序的可读性很差。所以new/delete 必须配对使用，malloc/free 也一样。</p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-15 18:11 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>stdin与STDIN_FILENO</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34892.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Mon, 15 Oct 2007 10:07:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34892.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34892.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34892.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34892.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在unix系统调用中,标准输入描述字用stdin,标准输出用stdout,标准出错用stderr表示,但在一些调用函数,引用了STDIN_FILENO表示标准输入才,同样,标准出入用STDOUT_FILENO,标准出错用STDERR_FILENO.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;请问,他们有什么区别吗?<br>stdin等是FILE *类型，属于标准I/O，在&lt;stdio.h&gt;。<br>STDIN_FILENO等是文件描述符，是非负整数，一般定义为0, 1, 2，属于没有buffer的I/O，直接调用系统调用，在&lt;unistd.h&gt;。<br>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-15 18:07 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fflush详解</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34891.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Mon, 15 Oct 2007 10:06:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34891.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34891.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34891.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34891.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34891.html</trackback:ping><description><![CDATA[<p>1、为什么 fflush(stdin) 是错的</p>
<p>首先请看以下程序：<br>#include &lt;stdio.h&gt;</p>
<p>int main( void )<br>{<br>&nbsp;int i;</p>
<p>&nbsp; for (;;) <br>&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fputs("Please input an integer: ", stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d", &amp;i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%d\n", i);<br>&nbsp; }<br>&nbsp; return 0;<br>}</p>
<p>这个程序首先会提示用户输入一个整数，然后等待用户输入，如果用户输入的是整数，程序会输出刚才输入的整数，并且再次提示用户输入一个整数，然后等待用户输入。但是一旦用户输入的不是整数（如小数或者字母），假设 scanf 函数最后一次得到的整数是 2 ，那么程序会不停地输出&#8220;Please input an integer: 2&#8221;。这是因为 scanf("%d", &amp;i); 只能接受整数，如果用户输入了字母，则这个字母会遗留在&#8220;输入缓冲区&#8221;中。因为缓冲中有数据，故而 scanf 函数不会等待用户输入，直接就去缓冲中读取，可是缓冲中的却是字母，这个字母再次被遗留在缓冲中，如此反复，从而导致不停地输出&#8220;Please input an integer: 2&#8221;。<br>&nbsp;<br>也许有人会说：&#8220;居然这样，那么在 scanf 函数后面加上&#8216;fflush(stdin);&#8217;，把输入缓冲清空掉不就行了？&#8221;然而这是错的！C和C++的标准里从来没有定义过 fflush(stdin)。也许有人会说：&#8220;可是我用 fflush(stdin) 解决了这个问题，你怎么能说是错的呢？&#8221;的确，某些编译器（如VC6）支持用 fflush(stdin) 来清空输入缓冲，但是并非所有编译器都要支持这个功能（linux 下的 gcc 就不支持），因为标准中根本没有定义 fflush(stdin)。MSDN 文档里也清楚地写着fflush on input stream is an extension to the C standard（fflush 操作输入流是对 C 标准的扩充）。当然，如果你毫不在乎程序的移植性，用 fflush(stdin) 也没什么大问题。以下是 C99 对 fflush 函数的定义：</p>
<p>int fflush(FILE *stream);<br>&nbsp;<br>如果 stream 指向输出流或者更新流（update stream），并且这个更新流<br>最近执行的操作不是输入，那么 fflush 函数将把这个流中任何待写数据传送至<br>宿主环境（host environment）写入文件。否则，它的行为是未定义的。</p>
<p>原文如下：<br>int fflush(FILE *stream);<br>If stream points to an output stream or an update stream in which<br>the most recent operation was not input, the fflush function causes<br>any unwritten data for that stream to be delivered to the host environment<br>to be written to the file; otherwise, the behavior is undefined.</p>
<p>&nbsp;&nbsp;其中，宿主环境可以理解为操作系统或内核等。<br>&nbsp;&nbsp;&nbsp; 由此可知，如果 stream 指向输入流（如 stdin），那么 fflush 函数的行为是不确定的。故而使用 fflush(stdin)&nbsp; 是不正确的，至少是移植性不好的。</p>
<p>2、清空输入缓冲区的方法</p>
<p>&nbsp;虽然不可以用 fflush(stdin)，但是我们可以自己写代码来清空输入缓冲区。只需要在 scanf 函数后面加上几句简单的代码就可以了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* C 版本 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;stdio.h&gt; </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int main( void )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i, c;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( ; ; )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fputs("Please input an integer: ", stdout);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d", &amp;i);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( feof(stdin) || ferror(stdin) )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { /* 如果用户输入文件结束标志（或文件已被读完）， */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 或者发生读写错误，则退出循环&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* do something */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 没有发生错误，清空输入流。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 通过 while 循环把输入流中的余留数据&#8220;吃&#8221;掉 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ( (c = getchar()) != '\n' &amp;&amp; c != EOF ) ;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 使用 scanf("%*[^\n]"); 也可以清空输入流， */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* 不过会残留 \n 字符。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%d\n", i);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* C++ 版本 */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;iostream&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;limits&gt; // 为了使用numeric_limits </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; using std::cout;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using std::endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using std::cin; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using std::numeric_limits;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; using std::streamsize; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; int main()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int value; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for ( ; ; )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Enter an integer: ";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cin &gt;&gt; value;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( cin.eof() || cin.bad() )<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { // 如果用户输入文件结束标志（或文件已被读完），<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 或者发生读写错误，则退出循环</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do something<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 读到非法字符后，输入流将处于出错状态，<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 为了继续获取输入，首先要调用 clear 函数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 来清除输入流的错误标记，然后才能调用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ignore 函数来清除输入流中的数据。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cin.clear();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // numeric_limits&lt;streamsize&gt;::max() 返回输入缓冲的大小。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ignore 函数在此将把输入流中的数据清空。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 这两个函数的具体用法请读者自行查询。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cin.ignore( numeric_limits&lt;streamsize&gt;::max(), '\n' );</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; value &lt;&lt; '\n';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34891.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-15 18:06 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/15/34891.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP中32位IP地址与字符串转化</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34739.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Thu, 11 Oct 2007 15:32:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34739.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34739.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34739.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34739.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34739.html</trackback:ping><description><![CDATA[<font style="COLOR: #020000" color=#cccccc>&nbsp;&nbsp;&nbsp; 在网络上面我们用的IP都是数字加点(192.168.0.1)构成的,&nbsp;而在struct&nbsp;in_addr结构中用的是32位的IP,我们上面那个32位IP(C0A80001)是的192.168.0.1&nbsp;为了转换我们可以使用下面两个函数&nbsp; <br><br>&nbsp;&nbsp;&nbsp; int&nbsp;inet_aton(const&nbsp;char&nbsp;*cp,struct&nbsp;in_addr&nbsp;*inp) <br>&nbsp;&nbsp;&nbsp; char&nbsp;*inet_ntoa(struct&nbsp;in_addr&nbsp;in) <br><br>&nbsp;&nbsp;&nbsp; 函数里面&nbsp;a&nbsp;代表&nbsp;ascii&nbsp;n&nbsp;代表network.第一个函数表示将a.b.c.d的IP转换为32位的IP,存储在&nbsp;inp指针里面.第二个是将32位IP转换为a.b.c.d的格式.</font><span style="COLOR: #020000"> <br><br>&nbsp;&nbsp;&nbsp; 同样inet_addr也可以进行字符串到32位整形的转换：<br><br>&nbsp;&nbsp;&nbsp; 首先，假设你已经有了一个sockaddr_in结构体ina，你有一个IP地址"132.241.5.10"&nbsp;要储存在其中，你就要用到函数inet_addr(),将IP地址从&nbsp;点数格式转换成无符号长整型。使用方法如下：<br>&nbsp;&nbsp;&nbsp; ina.sin_addr.s_addr&nbsp;=&nbsp;inet_addr("132.241.5.10");<br>&nbsp;&nbsp;&nbsp; 有的也使用unsigned long dst_ip = inet_addr("");<br><br>&nbsp;&nbsp;&nbsp; 可见<font style="COLOR: #020000" color=#cccccc>IPv4&nbsp;套接口地址结构 <br>&nbsp;&nbsp;&nbsp; struct&nbsp;in_addr <br>&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; in_addr_t&nbsp;s_addr&nbsp;; <br>&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; //&nbsp;32bits&nbsp;IPv4&nbsp;地址 <br>&nbsp;&nbsp;&nbsp; //网络字节顺序&nbsp;Network&nbsp;Byte&nbsp;Order <br>&nbsp;&nbsp;&nbsp; 类似：<br>&nbsp;&nbsp;&nbsp; struct in_addr <br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; unsigned long s_addr; // that&#8217;s a 32-bit long, or 4 bytes<br>&nbsp;&nbsp;&nbsp; }; <br></font><br>&nbsp;&nbsp;&nbsp; 这里错误返回INADDR_NONE (实际上是-1，每位都是1)<br>&nbsp;&nbsp;&nbsp; 而另一个INADDR_ANY的值为0，意思是任何地址都可以。<br><br>&nbsp;&nbsp;&nbsp; 注意，inet_addr()返回的地址已经是网络字节格式，所以你无需再调用&nbsp;函数htonl()。<br>&nbsp;&nbsp;&nbsp; 我们现在发现上面的代码片断不是十分完整的，因为它没有错误检查。&nbsp;显而易见，当inet_addr()发生错误时返回-1。记住这些二进制数字？(无符 &nbsp;号数)-1仅仅和IP地址255.255.255.255相符合！这可是广播地址！大错特&nbsp;错！记住要先进行错误检查。<br>&nbsp;&nbsp;&nbsp; 好了，现在你可以将IP地址转换成长整型了。有没有其相反的方法呢？&nbsp;它可以将一个in_addr结构体输出成点数格式？这样的话，你就要用到函数&nbsp;inet_ntoa()("ntoa"的含义是"network&nbsp;to&nbsp;ascii")，就像这样：&nbsp;<br>&nbsp;&nbsp;&nbsp; printf("%s",inet_ntoa(ina.sin_addr));<br>&nbsp;&nbsp;&nbsp; 它将输出IP地址。需要注意的是inet_ntoa()将结构体in-addr作为一&nbsp;个参数，不是长整形。同样需要注意的是它返回的是一个指向一个字符的&nbsp;指针。<font color=#3300ff>它是一个由inet_ntoa()控制的静态的固定的指针，所以每次调用&nbsp;inet_ntoa()，它就将覆盖上次调用时所得的IP地址</font>。例如：<br>&nbsp;&nbsp;&nbsp; char&nbsp;*a1,&nbsp;*a2;<br>&nbsp;&nbsp;&nbsp; .<br>&nbsp;&nbsp;&nbsp; .<br>&nbsp;&nbsp;&nbsp; a1&nbsp;=&nbsp;inet_ntoa(ina1.sin_addr);&nbsp;/*&nbsp;这是198.92.129.1&nbsp;*/<br>&nbsp;&nbsp;&nbsp; a2&nbsp;=&nbsp;inet_ntoa(ina2.sin_addr);&nbsp;/*&nbsp;这是132.241.5.10&nbsp;*/<br>&nbsp;&nbsp;&nbsp; printf("address&nbsp;1:&nbsp;%s&nbsp;",a1);<br>&nbsp;&nbsp;&nbsp; printf("address&nbsp;2:&nbsp;%s&nbsp;",a2);<br>&nbsp;&nbsp;&nbsp; 输出如下：<br>&nbsp;&nbsp;&nbsp; address&nbsp;1:&nbsp;132.241.5.10<br>&nbsp;&nbsp;&nbsp; address&nbsp;2:&nbsp;132.241.5.10<br>&nbsp;&nbsp;&nbsp; 假如你需要保存这个IP地址，使用strcopy()函数来指向你自己的字符指针。 <br><br><br><br></span>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34739.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-11 23:32 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34739.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>字符串与数字之间的转化</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34737.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Thu, 11 Oct 2007 15:09:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34737.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34737.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34737.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34737.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34737.html</trackback:ping><description><![CDATA[atoi（将字符串转换成整型数） <br>相关函数 atof，atol，atrtod，strtol，strtoul <br><br>表头文件 #include&lt;stdlib.h&gt; <br><br>定义函数 int atoi(const char *nptr); <br><br>函数说明 atoi()会扫描参数nptr字符串，跳过前面的空格字符，直到遇上数字或正负符号才开始做转换，而再遇到非数字或字符串结束时('\0')才结束转换，并将结果返回。如果遇到错误返回0。 <br><br>返回值 返回转换后的整型数。如果都是字符串，则应该是0。 <br><br>附加说明 atoi()与使用strtol(nptr，(char**)NULL，10)；结果相同。 <br><br>范例 /* 将字符串a 与字符串b转换成数字后相加*/ <br>#include&lt;stdlib.h&gt; <br>mian() <br>{ <br>char a[]=&#8221;-100&#8221;; <br>char b[]=&#8221;456&#8221;; <br>int c; <br>c=atoi(a)+atoi(b); <br>printf(c=%d\n&#8221;,c); <br>} <br><br>执行 c=356 <br><br>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-11 23:09 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP中的服务信息函数</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34736.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Thu, 11 Oct 2007 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34736.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34736.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34736.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34736.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34736.html</trackback:ping><description><![CDATA[<font style="COLOR: #040000" color=#cccccc>在网络程序里面我们有时候需要知道端口.IP和服务信息.这个时候我们可以使用以下几个函数&nbsp; <br><br>&nbsp;int&nbsp;getsockname(int&nbsp;sockfd,struct&nbsp;sockaddr&nbsp;*localaddr,int&nbsp;*addrlen) <br>&nbsp;int&nbsp;getpeername(int&nbsp;sockfd,struct&nbsp;sockaddr&nbsp;*peeraddr,&nbsp;int&nbsp;*addrlen) <br>&nbsp;struct&nbsp;servent&nbsp;*getservbyname(const&nbsp;char&nbsp;*servname,const&nbsp;char&nbsp;*protoname) <br>&nbsp;struct&nbsp;servent&nbsp;*getservbyport(int&nbsp;port,const&nbsp;char&nbsp;*protoname) <br>&nbsp;struct&nbsp;servent <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*s_name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;正式服务名&nbsp;*/ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;**s_aliases;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;别名列表&nbsp;*/&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;s_port;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;端口号&nbsp;*/ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*s_proto;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;使用的协议，可以是"udp"或"tcp" */&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br><br>&nbsp;&nbsp;&nbsp; 一般我们很少用这几个函数.对应客户端,当我们要得到连接的端口号时在connect调用成功后使用可得到&nbsp;系统分配的端口号.对于服务端,我们用INADDR_ANY填充后,为了得到连接的IP我们可以在accept调用成功后&nbsp;使用而得到IP地址.&nbsp; <br><br>&nbsp;&nbsp;&nbsp; 在网络上有许多的默认端口和服务,比如端口21对ftp80对应WWW.为了得到指定的端口号的服务&nbsp;我们可以调用第四个函数,相反为了得到端口号可以调用第三个函数.</font><span style="COLOR: #040000"> <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 在/ect/services下面可以查看服务<br><br></span>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34736.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-11 23:06 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/11/34736.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sscanf函数</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/10/34665.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Wed, 10 Oct 2007 14:27:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/10/34665.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34665.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/10/34665.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34665.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34665.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天在网上看到sscan函数的用法，突然想到自己以前在解析一个"Software/V1.5.3/product"这种类似的字符串时，竟用C的char *一字节一字节判断，当时怎么没有想到用sscanf解析。sscanf返回的赋值的个数。<br><br>
<p><strong><font face="Times New Roman"><font size=3>1.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></strong><strong><font size=3>常见用法。</font></strong> </p>
<table style="BACKGROUND: #cccccc 0% 50%; BORDER-COLLAPSE: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellSpacing=0 cellPadding=0 bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td style="PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; WIDTH: 426.1pt; PADDING-TOP: 0cm; BACKGROUND-COLOR: transparent" vAlign=top width=568>
            <p><font face="Times New Roman">char str[512] = {0};</font></p>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sscanf("123456 ", "%s", str);</font></p>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; printf("str=%s\n", str);</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p><font size=3><font face="Times New Roman">&nbsp;</font></font></p>
<p><font face="Times New Roman"><font size=3>2.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=3><strong>取指定长度的字符串。</strong> 如在下例中，取最大长度为<font face="Times New Roman">4</font>字节的字符串。</font></p>
<table style="BACKGROUND: #cccccc 0% 50%; BORDER-COLLAPSE: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellSpacing=0 cellPadding=0 bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td style="PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; WIDTH: 426.1pt; PADDING-TOP: 0cm; BACKGROUND-COLOR: transparent" vAlign=top width=568>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; sscanf("123456 ", "%4s", str);</font></p>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; printf("str=%s\n", str);</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p><font size=3><font face="Times New Roman">&nbsp;</font></font></p>
<p><font face="Times New Roman"><font size=3>3.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=3><strong>取到指定字符为止的字符串。</strong> 如在下例中，取遇到空格为止字符串。</font></p>
<table style="BACKGROUND: #cccccc 0% 50%; BORDER-COLLAPSE: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellSpacing=0 cellPadding=0 bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td style="PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; WIDTH: 426.1pt; PADDING-TOP: 0cm; BACKGROUND-COLOR: transparent" vAlign=top width=568>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; sscanf("123456 abcdedf", "%[^ ]", str);</font></p>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; printf("str=%s\n", str);</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p><font size=3><font face="Times New Roman">&nbsp;</font></font></p>
<p><font face="Times New Roman"><font size=3>4.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=3><strong>取仅包含指定字符集的字符串。</strong> 如在下例中，取仅包含<font face="Times New Roman">1</font>到<font face="Times New Roman">9</font>和小写字母的字符串。</font></p>
<table style="BACKGROUND: #cccccc 0% 50%; BORDER-COLLAPSE: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellSpacing=0 cellPadding=0 bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td style="PADDING-RIGHT: 5.4pt; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; WIDTH: 426.1pt; PADDING-TOP: 0cm; BACKGROUND-COLOR: transparent" vAlign=top width=568>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; sscanf("123456abcdedfBCDEF", "%[1-9a-z]", str);</font></p>
            <p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; printf("str=%s\n", str);</font></p>
            </td>
        </tr>
    </tbody>
</table>
<p><font size=3><font face="Times New Roman">&nbsp;</font></font></p>
<p><font face="Times New Roman"><font size=3>5.</font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=3><strong>取到指定字符集为止的字符串。</strong> 如在下例中，取遇到大写字母为止的字符串。</font></p>
<p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; sscanf("123456abcdedfBCDEF", "%[^A-Z]", str);</font></p>
<p><font face="Times New Roman">&nbsp;&nbsp;&nbsp; printf("str=%s\n", str);</font></p>
<br><br>头文件&nbsp;&nbsp;#include&lt;stdio.h&gt; <br><br>定义函数&nbsp;&nbsp;int sscanf (const char *str,const char * format,........); <br><br>函数说明&nbsp;&nbsp;sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。格式转换形式请参考scanf()。转换后的结果存于对应的参数内。 <br><br>返回值&nbsp;&nbsp;成功则返回参数数目，失败则返回-1，错误原因存于errno中。 <br><br>范例&nbsp;&nbsp;#include&lt;stdio.h&gt; <br>main() <br>{ <br>int i; <br>unsigned int j; <br>char input[ ]=&#8221;10 0x1b aaaaaaaa bbbbbbbb&#8221;; <br>char s[5]; <br>sscanf(input,&#8221;%d %x %5[a-z] %*s %f&#8221;,&amp;i,&amp;j,s,s); <br>printf(&#8220;%d %d %s\n&#8221;,i,j,s); <br>} <br><br>执行&nbsp;&nbsp;10 27 aaaaa <br><br><br>sscanf(stringBuf.c_str(), "%20[^#]#%20[^\n]",......)语句中""中的内容含义为： <br><br>&#8220;%[ ]&#8221;符号用于声明字符串，它比&#8220;%s&#8221;更具体，可以用于设置读取的样式。例如&#8220;%[a-z]&#8221;只读取小写字母，读到其它字符就结束。注意，方括号中如果有&#8220;^&#8221;，代表一直读到某字符为止。例如： <br><br>&#8220;%[^#]&#8221;：读取字符串，一直到出现&#8220;＃&#8221;号为止。 <br><br>&#8220;%20[^#]&#8221;：读取20个字节的字符串，出现&#8220;＃&#8221;号时结束。 <br><br>所以，&#8220;%20[^#]#%20[^\n]&#8221;的意义就是， <br><br>读取两个20字节大小的字符串，第一个字符串可以用＃结束，第二个字符串可以用回车符结束。 <br><br>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34665.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-10 22:27 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/10/34665.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用gethostbyname由域名或主机名得IP地址(转载)</title><link>http://www.cnitblog.com/wujian-IT/archive/2007/10/09/34614.html</link><dc:creator>吴剑</dc:creator><author>吴剑</author><pubDate>Tue, 09 Oct 2007 15:00:00 GMT</pubDate><guid>http://www.cnitblog.com/wujian-IT/archive/2007/10/09/34614.html</guid><wfw:comment>http://www.cnitblog.com/wujian-IT/comments/34614.html</wfw:comment><comments>http://www.cnitblog.com/wujian-IT/archive/2007/10/09/34614.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/wujian-IT/comments/commentRss/34614.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wujian-IT/services/trackbacks/34614.html</trackback:ping><description><![CDATA[<p><font size=4>使用这个东西，首先要包含2个头文件：<br>#include &lt;netdb.h&gt;<br>#include &lt;sys/socket.h&gt;</font></p>
<p><font size=4>struct hostent *gethostbyname(const char *name);<br>这个函数的传入值是域名或者主机名，例如"www.google.cn</font><font size=4>","wpc"等等。<br>传出值，是一个hostent的结构（如下）。如果函数调用失败，将返回NULL。</font></p>
<p><font size=4>struct hostent <br>{<br>&nbsp; char&nbsp; *h_name;<br>&nbsp; char&nbsp; **h_aliases;<br>&nbsp; int&nbsp;&nbsp; h_addrtype;<br>&nbsp; int&nbsp;&nbsp; h_length;<br>&nbsp; char&nbsp; **h_addr_list;<br>};<br>解释一下这个结构：<br>其中，<br>&nbsp; char *h_name 表示的是主机的规范名。例如</font>www.google.com<font size=4>的规范名其实是</font>www.l.google.com<font size=4>。<br>&nbsp; char&nbsp;&nbsp; **h_aliases 表示的是主机的别名.www.google.com</font><font size=4>就是google他自己的别名。有的时候，有的主机可能有好几个别名，这些，其实都是为了易于用户记忆而为自己的网站多取的名字。<br>&nbsp; int&nbsp;&nbsp; h_addrtype 表示的是主机ip地址的类型，到底是ipv4(AF_INET)，还是pv6(AF_INET6)<br>&nbsp; int&nbsp;&nbsp; h_length 表示的是主机ip地址的长度<br>&nbsp; int&nbsp;&nbsp; **h_addr_lisst 表示的是主机的ip地址，注意，这个是以网络字节序存储的。千万不要直接用printf带%s参数来打这个东西，会有问题的哇。所以到真正需要打印出这个IP的话，需要调用inet_ntop()。</font></p>
<p><font size=4>const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) ：<br>这个函数，是将类型为af的网络地址结构src，转换成主机序的字符串形式，存放在长度为cnt的字符串中。<br>这个函数，其实就是返回指向dst的一个指针。如果函数调用错误，返回值是NULL。</font></p>
<p>&nbsp;<br><font size=4>下面是例程，有详细的注释。</font></p>
<p><font size=4>#include &lt;netdb.h&gt;<br>#include &lt;sys/socket.h&gt;</font></p>
<p><font size=4>int main(int argc, char **argv)<br>{<br>&nbsp;&nbsp;&nbsp; char *ptr,**pptr;<br>&nbsp;&nbsp;&nbsp; struct hostent *hptr;<br>&nbsp;&nbsp;&nbsp; char str[32];</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; /* 取得命令后第一个参数，即要解析的域名或主机名 */<br>&nbsp;&nbsp;&nbsp; ptr = argv[1];</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; /* 调用gethostbyname()。调用结果都存在hptr中 */<br>&nbsp;&nbsp;&nbsp; if((hptr = gethostbyname(ptr)) == NULL)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; printf("gethostbyname error for host:%s\n", ptr);<br>&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; return 0; /* 如果调用gethostbyname发生错误，返回1 */<br>&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; /* 将主机的规范名打出来 */<br>&nbsp;&nbsp;&nbsp; printf("official hostname:%s\n",hptr-&gt;h_name);</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; /* 主机可能有多个别名，将所有别名分别打出来 */<br>&nbsp;&nbsp;&nbsp; for(pptr = hptr-&gt;h_aliases; *pptr != NULL; pptr++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("&nbsp; alias:%s\n",*pptr);</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; /* 根据地址类型，将地址打出来 */<br>&nbsp;&nbsp;&nbsp; switch(hptr-&gt;h_addrtype)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; case AF_INET:<br>&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; case AF_INET6:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pptr=hptr-&gt;h_addr_list;</font></p>
<p><font size=4>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; /* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; for(;*pptr!=NULL;pptr++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("&nbsp; address:%s\n", inet_ntop(hptr-&gt;h_addrtype,&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *pptr, str, sizeof(str)));<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; default:<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("unknown address type\n");<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; }</font></p>
<p><font size=4>&nbsp;&nbsp;&nbsp; return 0;<br>}<br></font></p>
<img src ="http://www.cnitblog.com/wujian-IT/aggbug/34614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wujian-IT/" target="_blank">吴剑</a> 2007-10-09 23:00 <a href="http://www.cnitblog.com/wujian-IT/archive/2007/10/09/34614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>