<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Program/Cpp | Hessian's Blog</title><link>https://hessian.cn/cat/program/cpp</link><description>Hessian 的技术笔记：Linux、C++、网络与嵌入式</description><language>zh-CN</language><atom:link href="https://hessian.cn/cat/program/cpp/index.xml" rel="self" type="application/rss+xml"/><item><title>*HACK* 为QT的TCP socket连接绑定本地IP地址</title><link>https://hessian.cn/p/1401.html</link><pubDate>Fri, 10 Jan 2014 01:27:42 +0800</pubDate><guid>https://hessian.cn/p/1401.html</guid><description>有时候我们会在机器上同时绑定多个IP地址（可能都是在一个网卡上），但是我们却无法指定程序使用哪个IP地址去建立连接。&#10;虽然我之前的另一篇文章《在Windows/Linux下程序指定IP地址》讲过一种hack的办法，但是并不总是那么有效。就比如博主最近遇到的一个QT写的程序，不知道为什么就是bind不了，不过万幸的是我们有源代码。&#10;通过修改QT框架的QNativeSocketEngine的实现我们还是可以bind到我们需要的IP地址的。&#10;</description></item><item><title>在Windows/Linux下让程序指定出口IP地址</title><link>https://hessian.cn/p/1378.html</link><pubDate>Fri, 18 Oct 2013 01:43:00 +0800</pubDate><guid>https://hessian.cn/p/1378.html</guid><description>Windows/Unix* 系统都支持为一个网卡绑定多个IP地址，但是通常操作系统会根据路由表自动选择IP地址，应用程序使用哪个IP地址用户无法主动控制。本文分别讲解在Linux和Windows下为应用程序绑定指定IP地址的方法。&#10;</description></item><item><title>[推荐]C代码优化方案</title><link>https://hessian.cn/p/461.html</link><pubDate>Fri, 16 May 2008 13:10:00 +0800</pubDate><guid>https://hessian.cn/p/461.html</guid><description>地址：http://blog.csdn.net/quanming1119/archive/2005/08/10/450545.aspx&#10;华中科技大学计算机学院&#10;姓名：    王全明&#10;QQ：       375288012&#10;</description></item><item><title>GCC编译优化设置</title><link>https://hessian.cn/p/319.html</link><pubDate>Thu, 20 Mar 2008 10:25:00 +0800</pubDate><guid>https://hessian.cn/p/319.html</guid><description>检查你的gcc版本： # gcc –version&#10;* 获取你的cpu的型号： # cat /proc/cpuinfo&#10;* 在/etc/下建立make.conf文件，并根据cpu的型号写入不同内容(注意你的gcc版本必须在3.0以上)：</description></item><item><title>C/C++ 经典算法实例</title><link>https://hessian.cn/p/416.html</link><pubDate>Mon, 17 Mar 2008 18:30:00 +0800</pubDate><guid>https://hessian.cn/p/416.html</guid><description>二分查找的代码.&#10;int bfind(int* a,int len,int val)&#10;{&#10;int m = len/2;&#10;int l = 0;&#10;int r = len;&#10;while(l!=m &amp;&amp; r!= m)&#10;{&#10;if(a[m] &gt; val)&#10;{&#10;r = m;&#10;m = (m+l)/2;&#10;}&#10;else if(a[m] &lt; val)&#10;{&#10;l = m;&#10;m = (m+r)/2;&#10;}&#10;else&#10;return m;&#10;}&#10;return -1; //没有找到&#10;}&#10;写出在母串中查找子串出现次数的代码.&#10;</description></item><item><title>[转]MD5算法的C++实现 &lt;一&gt;</title><link>https://hessian.cn/p/310.html</link><pubDate>Tue, 11 Dec 2007 18:38:00 +0800</pubDate><guid>https://hessian.cn/p/310.html</guid><description>转自：http://www.cnblogs.com/flying_bat/archive/2007/09/25/905133.html&#10;百度太可恶了…..文章长度限制…这么厉害…..&#10;哼…..我不贴内容了还不行么&#10;源代码下载：点击下载</description></item><item><title>[转]md5加密算法c实现，七分注释</title><link>https://hessian.cn/p/653.html</link><pubDate>Tue, 11 Dec 2007 17:55:00 +0800</pubDate><guid>https://hessian.cn/p/653.html</guid><description>转自：http://blog.csdn.net/coder0621/archive/2007/03/23/1539208.aspx&#10;记得当初自己刚开始学习md5的时候，从网上搜了很多关于算法的原理和文字性的描述的东西，但是看了很久一直没有搞 懂，搜c的源代码又很少。直到后来学习rsa算法的时候，从网上下了1991年的欧洲的什么组织写的关于rsa、des、md5算法的c源代码（各部分代 码混在一块的，比如rsa用到的随机大素数就是用机器的随机时间的md5哈希值获得的）。我才彻底把md5弄明白了。这里的代码就是我从那里面分离出来 的，代码的效率和可重用性都是很高的。整理了一下希望对需要的朋友能够有帮助。&#10;</description></item><item><title>C++ 编程注意事项</title><link>https://hessian.cn/p/307.html</link><pubDate>Thu, 23 Aug 2007 02:44:00 +0800</pubDate><guid>https://hessian.cn/p/307.html</guid><description>条款1：尽量用const和inline而不用#define 条款2：尽量用&lt;iostream&gt;而不用&lt;stdio.h&gt; 条款3：尽量用new和delete而不用malloc和free 条款4：尽量使用c++风格的注释 条款5：对应的new和delete要采用相同的形式 条款6：析构函数里对指针成员调用delete 条款7：预先准备好内存不够的情况 条款8: 写operator new和operator delete时要遵循常规 条款9: 避免隐藏标准形式的new 条款10: 如果写了operator new就要同时写operator delete 条款11: 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符 条款12: 尽量使用初始化而不要在构造函数里赋值 条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同 条款14: 确定基类有虚析构函数 条款15: 让operator=返回*this的引用 条款16: 在operator=中对所有数据成员赋值 条款17: 在operator=中检查给自己赋值的情况 条款18: 争取使类的接口完整并且最小 条款19: 分清成员函数，非成员函数和友元函数 条款20: 避免public接口出现数据成员 条款21: 尽可能使用const 条款22: 尽量用“传引用”而不用“传值” 条款23: 必须返回一个对象时不要试图返回一个引用 条款24: 在函数重载和设定参数缺省值间慎重选择 条款25: 避免对指针和数字类型重载 条款26: 当心潜在的二义性 条款27: 如果不想使用隐式生成的函数就要显式地禁止它 条款28: 划分全局名字空间 条款29: 避免返回内部数据的句柄 条款30: 避免这样的成员函数：其返回值是指向成员的非const指针或引用， 但成员的访问级比这个函数要低 条款31: 千万不要返回局部对象的引用，也不要返回函数内部用new初始化 的指针的引用 条款32: 尽可能地推迟变量的定义 条款33: 明智地使用内联 条款34: 将文件间的编译依赖性降至最低 条款35: 使公有继承体现 "是一个" 的含义 条款36: 区分接口继承和实现继承 条款37: 决不要重新定义继承而来的非虚函数 条款38: 决不要重新定义继承而来的缺省参数值 条款39: 避免 "向下转换" 继承层次 条款40: 通过分层来体现 "有一个" 或 "用…来实现" 条款41: 区分继承和模板 条款42: 明智地使用私有继承 条款43: 明智地使用多继承 条款44: 说你想说的；理解你所说的 条款45: 弄清C++在幕后为你所写、所调用的函数 条款46: 宁可编译和链接时出错，也不要运行时出错 条款47: 确保非局部静态对象在使用前被初始化 条款48: 重视编译器警告 条款49: 熟悉标准库 条款50: 提高对C++的认识&#10;</description></item><item><title>计算代码行数的小程序</title><link>https://hessian.cn/p/397.html</link><pubDate>Thu, 19 Jul 2007 20:57:00 +0800</pubDate><guid>https://hessian.cn/p/397.html</guid><description>/******************************************&#10;*   使用方法….在命令行下运行&#10;*   lineamount.exe &gt; 要输出行数的文件名&#10;*   输入含有要统计的文件路径的文件&#10;*&#10;*******************************************/&#10;#include "stdafx.h"&#10;#include "stdio.h"&#10;#include &lt;iostream&gt;&#10;#include &lt;string&gt;&#10;#include &lt;fstream&gt;&#10;</description></item><item><title>[C相关]链表的c语言实现</title><link>https://hessian.cn/p/504.html</link><pubDate>Mon, 25 Jun 2007 01:41:00 +0800</pubDate><guid>https://hessian.cn/p/504.html</guid><description> 准备：动态内存分配&#10;一、为什么用动态内存分配&#10;但我们未学习链表的时候，如果要存储数量比较多的同类型或同结构的数据的时候，总是使用一个数组。比如说我们要存储一个班级学生的某科分数，总是定义一个float型（存在0.5分）数组：&#10;float score[30];&#10;但是，在使用数组的时候，总有一个问题困扰着我们：数组应该有多大？&#10;在很多的情况下，你并不能确定要使用多大的数组，比如上例，你可能并不知道该班级的学生的人数，那么你就要把数组定义得足够大。这样，你的程序在运行时就 申请了固定大小的你认为足够大的内存空间。即使你知道该班级的学生数，但是如果因为某种特殊原因人数有增加或者减少，你又必须重新去修改程序，扩大数组的 存储范围。这种分配固定大小的内存分配方法称之为静态内存分配。但是这种内存分配的方法存在比较严重的缺陷，特别是处理某些问题时：在大多数情况下会浪费 大量的内存空间，在少数情况下，当你定义的数组不够大时，可能引起下标越界错误，甚至导致严重后果。&#10;那么有没有其它的方法来解决这样的外呢体呢？有，那就是动态内存分配。&#10;所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空 间，而是由系统根据程序的需要即时分配，且分配的大小就是程序要求的大小。从以上动、静态内存分配比较可以知道动态内存分配相对于静态内存分配的特点：&#10;1、不需要预先分配存储空间；&#10;2、分配的空间可以根据程序的需要扩大或缩小。&#10;二、如何实现动态内存分配及其管理&#10;要实现根据程序的需要动态分配存储空间，就必须用到以下几个函数&#10;1、malloc函数&#10;malloc函数的原型为：&#10;void *malloc (unsigned int size)&#10;其作用是在内存的动态存储区中分配一个长度为size的连续空间。其参数是一个无符号整形数，返回值是一个指向所分配的连续存储域的起始地址的指针。还有 一点必须注意的是，当函数未能成功分配存储空间（如内存不足）就会返回一个NULL指针。所以在调用该函数时应该检测返回值是否为NULL并执行相应的操 作。&#10;下例是一个动态分配的程序例题（1）：&#10;#include &lt;stdio.h&gt;&#10;#include &lt;stdlib.h&gt;&#10;#include &lt;malloc.h&gt;&#10;main()&#10;{&#10;int count,*array; /*count是一个计数器，array是一个整型指针，也可以理解为指向一个整型数组的首地址*/&#10;if((array=(int *) malloc(10*sizeof(int)))==NULL)&#10;{&#10;printf("不能成功分配存储空间。");&#10;exit(1);&#10;}&#10;for (count=0;count&lt;10;count++) /*给数组赋值*/&#10;array[count]=count;&#10;for(count=0;count&lt;10;count++) /*打印数组元素*/&#10;printf("%2d",array[count]);&#10;free(array);&#10;}&#10;上例中动态分配了10个整型存储区域，然后进行赋值并打印。例中if((array(int *) malloc(10*sizeof(int)))==NULL)语句可以分为以下几步：&#10;1）分配10个整型的连续存储空间，并返回一个指向其起始地址的整型指针&#10;2）把此整型指针地址赋给array&#10;3）检测返回值是否为NULL&#10;2、free函数&#10;由于内存区域总是有限的，不能不限制地分配下去，而且一个程序要尽量节省资源，所以当所分配的内存区域不用时，就要释放它，以便其它的变量或者程序使用。这时我们就要用到free函数。&#10;其函数原型是：&#10;void free(void *p)&#10;作用是释放指针p所指向的内存区。&#10;其参数p必须是先前调用malloc函数或calloc函数（另一个动态分配存储区域的函数）时返回的指针。给free函数传递其它的值很可能造成死机或其它灾难性的后果。&#10;注意：这里重要的是指针的值，而不是用来申请动态内存的指针本身。例：&#10;int *p1,*p2;&#10;p1=malloc(10*sizeof(int));&#10;p2=p1;&#10;……&#10;free(p2) /*或者free(p2)*/&#10;malloc返回值赋给p1，又把p1的值赋给p2，所以此时p1，p2都可作为free函数的参数。&#10;malloc函数是对存储区域进行分配的。&#10;free函数是释放已经不用的内存区域的。&#10;所以由这两个函数就可以实现对内存区域进行动态分配并进行简单的管理了。&#10;本节课后&#10;问题：&#10;1、free函数有什么用处？&#10;2、stdio.h、stdlib.h、malloc.h 这三个头文件在程序例题（1）中起到了什么作用？&#10;3、#include &lt;stdio.h&gt;和#incluce "stdio.h"有什么不同？&#10;体会：&#10;1、对照程序例题（1）体会“(array=(int *) malloc(10*sizeof(int)))==NULL”这一句的写法。&#10;目的：&#10;1、为什么要“动态分配内存”，如何做到“动态内存分配”。&#10;</description></item><item><title>关于Qt</title><link>https://hessian.cn/p/552.html</link><pubDate>Wed, 20 Jun 2007 08:55:00 +0800</pubDate><guid>https://hessian.cn/p/552.html</guid><description>Qt是一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立 艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的很容易扩展，并且 允许真正地组件编程。&#10;</description></item><item><title>北京二手手机怎么买？ 有内容！</title><link>https://hessian.cn/p/634.html</link><pubDate>Sun, 03 Jun 2007 18:17:00 +0800</pubDate><guid>https://hessian.cn/p/634.html</guid><description>北京的二手手机市场比较多，但是其中比较著名的应该是公主坟周边的飞新马二手商城，还有木樨园和西直门等三家二手手机市场&#10;西直门地区二手手机市场&#10;适合卖手机&#10;</description></item><item><title>【转】推荐的C++书籍以及阅读顺序</title><link>https://hessian.cn/p/342.html</link><pubDate>Sat, 02 Jun 2007 11:07:00 +0800</pubDate><guid>https://hessian.cn/p/342.html</guid><description>当读者有一定c/c++基础&#10;推荐的阅读顺序:&#10;level 1&#10;从&lt;&lt;essential c++&gt;&gt;开始，短小精悍，可以对c++能进一步了解其特性&#10;以&lt;&lt;c++ primer&gt;&gt;作字典和课外读物，因为太厚不可能一口气看完&#10;</description></item><item><title>VC++编程实现对火焰的计算机动态仿真</title><link>https://hessian.cn/p/541.html</link><pubDate>Fri, 11 May 2007 17:07:00 +0800</pubDate><guid>https://hessian.cn/p/541.html</guid><description>摘要：本文通过对真实火焰物理特性的分析，建立了火焰动态燃烧的数学模型，并在此数学模型基础之上借助于DirectDraw技术对图形显示的加速，在VC++ 6.0下对火焰作了效果非常逼真的计算机动态仿真。&#10;</description></item><item><title>嗅探原理与反嗅探技术详解</title><link>https://hessian.cn/p/434.html</link><pubDate>Sat, 05 May 2007 04:20:00 +0800</pubDate><guid>https://hessian.cn/p/434.html</guid><description>渗透实验室：大皮球 一．嗅探器的基础知识 1．1 什么是嗅探器？ 嗅探器的英文写法是Sniff，可以理解为一个安装在计算机上的窃听设备它可以用来窃听计算机在网络上所产生的众多的信息。简单一点解释：一部电话的窃听装置, 可以用来窃听双方通话的内容，而计算机网络嗅探器则可以窃听计算机程序在网络上发送和接收到的数据。</description></item><item><title>VXD,KMD,WDM基本概念</title><link>https://hessian.cn/p/418.html</link><pubDate>Wed, 18 Apr 2007 07:34:00 +0800</pubDate><guid>https://hessian.cn/p/418.html</guid><description>作者:陆麟&#10;来来来,一起进入这黑黑的驱动程序世界.:)&#10;这里要讲的是Vxd,Kernel Mode Driver,和WDM的一些基本问题.&#10;什么是VxD?&#10;VxD乃 VIRTUAL X DRIVER.哎,说了也白说.其实就是虚拟设备驱动程序.是系统用于对各种硬件资源识别,管理,维护运作的扩展.VXD和VMM(虚拟机管理器)一起合作,维持着系统的运作.VxD模式从WIN3X时代就开始了.一直到了WIN98还一直在MS的WIN系列操作系统中起主导作用.VxD运作在INTEL系列CPU保护模式下的RING0.拥有对硬件的最高控制权.&#10;</description></item><item><title>Visual C++ MFC 简明教程 [3]</title><link>https://hessian.cn/p/560.html</link><pubDate>Wed, 18 Apr 2007 07:08:00 +0800</pubDate><guid>https://hessian.cn/p/560.html</guid><description>CButton类 在上一讲中所讨论的CStatic控制是唯一不响应用户时间的控制。Windows中所有的其它控制都可响应用户事件。第一，当用户处理它们时， 它们会自动更新其外观(例如，当用户单击按钮时，按钮会自己加亮以给用户一个反馈)。第二，每个不同的控制都要发送信息给你的代码以使程序能响应用户的需 要。例如，当单击按钮时，按钮就会发送一个命令消息。如果你编写代码接收消息，则你的代码就能响应用户事件。 为了理解这个过程，我们从CButton控制开始。下面的代码说明了建立按钮的过程： // button1.cpp #include #define IDB_BUTTON 100 // Declare the application class class CButtonApp : public CWinApp { public: virtual BOOL InitInstance(); }; // Create an instance of the application class CButtonApp ButtonApp; // Declare the main window class class CButtonWindow : public CFrameWnd { CButton *button; public: CButtonWindow(); }; // The InitInstance function is called once // when the application first executes BOOL CButtonApp::InitInstance() { m_pMainWnd = new CButtonWindow(); m_pMainWnd-&gt;ShowWindow(m_nCmdShow); m_pMainWnd-&gt;UpdateWindow(); return TRUE; } // The constructor for the window class CButtonWindow::CButtonWindow() { CRect r; // Create the window itself Create(NULL, "CButton Tests", WS_OVERLAPPEDWINDOW, CRect(0,0,200,200));</description></item><item><title>Visual C++ MFC 简明教程 [1]</title><link>https://hessian.cn/p/469.html</link><pubDate>Wed, 18 Apr 2007 07:07:00 +0800</pubDate><guid>https://hessian.cn/p/469.html</guid><description>Visual C++ MFC 简明教程 第一部分：MFC导论 Visual C++ 不仅仅是一个编译器。它是一个全面的应用程序开发环境，使用它你充分利用具有面向对象特性的 C++ 来开发出专业级的 Windows 应用程序。为了能充分利用这些特性，你必须理解 C++ 程序设计语言。掌握了C++，你就必须掌握 Microsoft 基本类库 (MFC) 的层次结构。该层次 结构包容了 Windows API 中的用户界面部分，并使你能够很容易地以面向对象的方式建立 Windows 应用程序。这种层次结构适用于所有版本的 Windows 并彼此兼容。你用 MFC 所建立的代码是完全可移植的。 该教程将向你介绍MFC的基本概念和术语以及事件驱动程序设计方法。在本节中，你将会输入、编译和运行一个简单的MFC程序。下一节中将向你详细解释这些代码。第三部分讨论了MFC控制和如何定制它们。第四部分将介绍消息映射，你将会处理MFC的事件。</description></item><item><title>Visual C++ MFC 简明教程 [2]</title><link>https://hessian.cn/p/336.html</link><pubDate>Wed, 18 Apr 2007 07:07:00 +0800</pubDate><guid>https://hessian.cn/p/336.html</guid><description>窗口对象 MFC 定义了两个类型的窗口: 1) 框架窗口，它是一个全功能的窗口，可以改变大小、最小化、最大化等等; 2) 对话框窗口，它不能改变大小。框架窗口是典型的主应用程序窗口。 在下面的代码中，从 CFrameWnd 中继承了一个新的类 CHelloWindow: 11 // Declare the main window class 12 class CHelloWindow : public CFrameWnd 13 { 14 CStatic* cs; 15 public: 16 CHelloWindow(); 17 }; 它包括一个新的构造函数，同时还有一个指向程序中所使用的唯一用户界面控制的数据成员。你多建立的每个应用程序在主窗口中都会有唯一的一组控制。 因此，继承类将有一个重载的构造函数以用来建立主窗口所需要的所有控制。典型情况下，该类会包含有一个析构函数以便在窗口关闭时来删除他们。我们这里没有 使用析构函数。在第四讲中，我们将会看到继承窗口类也会说明一个消息处理函数来处理这些控制在响应用户事件所产生的消息。 典型地，一个应用程序将有一个主应用程序窗口。因此，CHelloApp 应用程序类定义了一个名为 m_pMainWnd 成员变量来指向主窗口。为了建立该程序的主窗口，InitInstance 函数(第18至26行)建立了一个 CHelloWindow 事例，并使用 m_pMainWnd 来指向一个新的窗口。我们的 CHelloWindow 对象是在第22行建立的: 18 // The InitInstance function is called each 19 // time the application first executes. 20 BOOL CHelloApp::InitInstance() 21 { 22 m_pMainWnd = new CHelloWindow(); 23 m_pMainWnd-&gt;ShowWindow(m_nCmdShow); 24 m_pMainWnd-&gt;UpdateWindow(); 25 return TRUE; 26 } 只建立一个简单的框架窗口是不够的。还要确保窗口能正确地出现在屏幕上。首先，代码必须要调用窗口的 ShowWindow 函数以使窗口出现在屏幕上(第23行)。其次，程序必须要调用 UpdateWindow 函数来确保窗口中的每个控制和输出能正确地出现在屏幕上(第24行)。 你可能奇怪，ShowWindow 和 UpdateWindow 函数是在哪儿定义的。例如，如果你要查看以便了解它们，你可能要查看 MFC 的帮助文件中的 CFrameWnd 定义部分。但是 CFrameWnd 中并不包含有这些成员函数。CFrameWnd 是从 CWnd 类继承来的。你可以查看 MFC 文档中的 CWnd，你会发现它包含有200多个不同的成员函数。显然，你不能在几分钟内掌握这些函数，但是你可以掌握其中的几个，如 ShowWindow 和UpdateWindow。 现在让我们花几分钟来看一下 MFC 帮助文件中的 CWnd::ShowWindow 函数。为此，你你可以单击帮助文件中的 Search 按钮，并输入“ShowWindow”。找到后，你会注意到，ShowWindow 只有一个参数，你可以设置不同的参数值。我们把它设置成我们程序中 CHelloApp 的数据成员变量 m_nCmdShow (第23行)。m_nCmdShow 变量是用来初始化应用程序启动的窗口显示方式的。例如，用户可能在程序管理器中启动应用程序，并可通过应用程序属性对话框来告知程序管理器应用程序在启动 时要保持最小化状态。m_nCmdShow 变量将被设置成 SW_SHOWMINIMIZED，并且应用程序会以图标的形式来启动，也就是说，程序启动后，是一个代表该程序的图标。m_nCmdShow 变量是一种外界与应用程序通讯的方式。如果你愿意，你可以用不同的 m_nCmdShow 值来试验 ShowWindow 的效果。但要重新编译程序才能看到效果。 第22行是初始化窗口。它为调用 new 函数分配内存。在这一点上，程序在执行时会调用CHelloWindow的构造函数。该构造函数在每次带类的事例被分配时都要调用。在窗口构造函数的内 部，窗口必须建立它自己。它是通过调用 CFrameWnd 的 Create 成员函数来实现的(第31行): 27 // The constructor for the window class 28 CHelloWindow::CHelloWindow() 29 { 30 // Create the window itself 31 Create(NULL, 32 "Hello World!", 33 WS_OVERLAPPEDWINDOW, 34 CRect(0,0,200,200)); 建立函数共传递了四个参数。通过查看 MFC 文档，你可以了解不同类型。NULL 参数表示使用缺省的类名。第二个参数为出现在窗口标题栏上的标题。第三个参数为窗口的类型属性。该程序使用了正常的、可覆盖类型的窗口。在下一讲中将详细 介绍类型属性。第四个参数指出窗口应该放在屏幕上的位置和大小，左上角为(0,0), 初始化大小为 200×200个象素。如果使用了 rectDefault，则 Windows 会为你自动放置窗口及大小。 因为我们的程序太简单了，所以它只在窗口中建立了一个静态文本控制。见第35至40行。下面将详细介绍。</description></item><item><title>【转】谁说 C宏 是 智者的利刃，愚者的恶梦!</title><link>https://hessian.cn/p/438.html</link><pubDate>Wed, 18 Apr 2007 03:56:00 +0800</pubDate><guid>https://hessian.cn/p/438.html</guid><description>水平不高不低的C++程序员最喜欢挂在嘴上的一句话就是：C宏，万恶之首，错误的开端，应该被废弃。&#10;请注意，我用了一句不敬的修饰语“水平不高不低的”。为什么这么说？因为水平低都插不上话，都在在静静地听老前辈布道呢。水平高的，比如Bane Stroustrup老人家，也只是说若干种场合下C++语言能够提供比C macro更好的解决方案，而没有完全否定C macro的价值。但是话就怕传来传去，一传就走样。久而久之，就被传成上面那句话。其实说来也很好笑：java程序员经常说java比C++好，说C+ +手动释放内存老搞内存泄漏；C++程序员便反驳说，那是你水平低不会用。但是谈到C宏，水平不高不低的C++程序员居然也走java的老路了——明明是 自己不会用，自己知道的少，却把责任推卸到C宏上。你自己笨我管不着，但是错误的言论如果误导后人就不好了吧。:)&#10;本文就举几个简单的使用C宏的例子，如果这些例子用C++不用宏的语法能更好的解决，那么你一定要回复blog告诉我，这样下次我就不乱说话了。否则，笑笑很生气，后果很严重。:)&#10;</description></item><item><title>递归的应用 — 最简单分形图形实现</title><link>https://hessian.cn/p/376.html</link><pubDate>Wed, 18 Apr 2007 03:50:00 +0800</pubDate><guid>https://hessian.cn/p/376.html</guid><description>作者：吉林大学　胡卓玮&#10;下载本文源代码&#10;图一 例子代码运行结果     大家在C/C++学习时都会遇到递归，课本上以汗诺塔为例进行讲解，然后大家都希望自己找到一个递归的实例。本文以一个最简单的分形图形来讲解递归的实现过程。&#10;    先来看看绘制这个分形图形的思路。如图二所示，给定两点（p1和p2）确定一条直线，计算这条直线的长度，如果长度小于预先设定的极限值则将这两个点用直 线相连，否则，取其1/3处点（点1）、2/3处点（点2），以及中点上方一个点（点3），这个点与第1点、第2点构成的直线与直线p1p2的夹角为60 度。判断这五个点按照顺序形成的四条直线的长度是否小于预先设定的极限值，如果小于，则在将相应的两个点相连在屏幕上显示一条直线，否则继续对相应两点形 成的直线进行以上判断。&#10;</description></item><item><title>启程动态数组V2.0</title><link>https://hessian.cn/p/522.html</link><pubDate>Wed, 18 Apr 2007 03:49:00 +0800</pubDate><guid>https://hessian.cn/p/522.html</guid><description>作者：黄建雄&#10;下载源代码&#10;简介&#10;大量数据的管理是很多程序员的心病，很难找到一个速度快、效率高、支持超大规模数据的表，在1.0版本的基础上，启程花血本写下了这个强化了数据插入 与删除的修正版，启程动态数组是一个功能强大的列表形数据管理链表，利用它可以轻松实现超大数据量的随机插入、删除、修改等操作，它另外一个特点就是速度 极快，内存利用率高。&#10;大量数据的管理必然需要占用大量的内存空间，如果这些数据占用的空间大小是随各种条件变化的，我们就不能使用数组来管理这些数据了（道理就不多说 了），这时我们需要一个动态数组。MFC提供了一个很好的动态数组类CArray，对于少量数据，使用CArray就足够好用了，但是对于大量数据 （10W级）它就力不从心了，因为它的本质就是一个数组，只不过对常用的插入、删除等操作进行了一个复杂的包装。为了解决这个问题，启程动态数组开创性地 将链表与数组巧妙的结合起来，既有数组的高速随机索引的优点，又有链表的数据量灵活多变的特点。&#10;</description></item><item><title>URL编码</title><link>https://hessian.cn/p/467.html</link><pubDate>Wed, 18 Apr 2007 03:48:00 +0800</pubDate><guid>https://hessian.cn/p/467.html</guid><description>作者： Chandrasekhar Vuppalapati 翻译：eastvc&#10;下载源代码&#10;本文的目的是设计一个完成URL编码的C++类。在我曾经的项目中，我需要从VC++ 6.0应用程序中POST数据，而这些数据需要进行URL编码。我在MSDN中查找能根据提供的字符串生成URL编码的相关类或API，但我没有找到，因 此我必须设计一个自己的URLEncode C++类。&#10;</description></item><item><title>简单快速的哈夫曼编码</title><link>https://hessian.cn/p/304.html</link><pubDate>Wed, 18 Apr 2007 03:48:00 +0800</pubDate><guid>https://hessian.cn/p/304.html</guid><description>作者：Hatem Mostafa 译者：happyparrot&#10;下载源代码&#10;介绍&#10;本文描述在网上能够找到的最简单，最快速的哈夫曼编码。本方法不使用任何扩展动态库，比如STL或者组件。只使用简单的C函数，比如：memset，memmove，qsort，malloc，realloc和memcpy。&#10;</description></item><item><title>VC++中用内存映射文件</title><link>https://hessian.cn/p/613.html</link><pubDate>Wed, 18 Apr 2007 03:37:00 +0800</pubDate><guid>https://hessian.cn/p/613.html</guid><description>在软件的开发过程中，有时需要控制一些程序使他们不能同时运行，也就是多个程序间互斥运行（还包括禁止同一程序运行多个实例）。针对这一问题，我们在Visual C++6.0中利用内存映射文件实现了多个程序间的互斥运行。内存映射文件可以创建一个没有和磁盘文件相联系的内存对象，将文件的信息映射到一个进程的地址空间上，我们可以访问该文件中的数据，就如同它位于内存中一样。同时，在程序设计中可以给内存映射文件对象起一个名字，这个名字在整个系统中是唯一的，这个名字可以在多个进程之间共享，通过名字共享能实现进行信息交换，进而实现多个程序间的互斥运行。&#10;</description></item><item><title>如何将一个文件分割成多个小文件</title><link>https://hessian.cn/p/632.html</link><pubDate>Wed, 18 Apr 2007 03:28:00 +0800</pubDate><guid>https://hessian.cn/p/632.html</guid><description>   你也许会遇到到这样一个问题？当你有一个较大的软件，而无法用一张软盘将其全部拷下时，你也许会想到该将它分解开，分盘拷回去后，再将它们合并起来。现在的这种分割工具很多，你想自己动手做一个适合自己的分割工具么？下面就让我用以前用VC做的一个＜袖珍文件分割器＞的例程来告诉你吧！程序运行后界面如下图： 基本构成思想：文件分割的基本思想比我之前发表的另一篇文章＜如何将多个文件合并为一个可执行程序＞的构成思想简单多了，它主要也分为分割文件和合并分割后的文件二大部分。分割文件，将原文件按指定分割大小进行等分，然后顺序读取其指定分割大小数据后到写到各自的新建文件中。合并文件，将各分割后的文件顺序读取后，写入到一个文件中既可。</description></item><item><title>用Visual C++操作INI文件</title><link>https://hessian.cn/p/331.html</link><pubDate>Wed, 18 Apr 2007 03:27:00 +0800</pubDate><guid>https://hessian.cn/p/331.html</guid><description>在我们写的程序当中,总有一些配置信息需要保存下来,以便完成程序的功能,最简单的办法就是将这些信息写入INI文件中,程序初始化时再读入.具体应用如下:&#10;</description></item><item><title>PE 格式学习总结（四）– PE文件中的资源</title><link>https://hessian.cn/p/354.html</link><pubDate>Wed, 18 Apr 2007 03:23:00 +0800</pubDate><guid>https://hessian.cn/p/354.html</guid><description>    程序所用到的各种资源，比如 bmp,cursor,menu,对话框等都存在PE文件中。&#10;    我们将详细介绍关于资源的各种结构，通过一个例子来说明资源及其相关结构是怎么放在PE文件中的。以及如何在遍历PE文件中的所有资源。我们只最终找到这些资源在文件中的位置和长度。而不具体分析某种资源的格式，比如有个BMP的资源，我们不分析BMP格式。</description></item><item><title>PE 格式学习总结（三）– PE文件中的输入函数</title><link>https://hessian.cn/p/382.html</link><pubDate>Wed, 18 Apr 2007 03:22:00 +0800</pubDate><guid>https://hessian.cn/p/382.html</guid><description>    关于输入部分，我们将详细介绍关于输入函数的各种结构，通过一个例子来说明输入函数及其相关结构是怎么放在PE文件中的。以及如何在PE文件中找到这些东西。</description></item><item><title>PE 格式学习总结（二）– PE文件中的输出函数</title><link>https://hessian.cn/p/649.html</link><pubDate>Wed, 18 Apr 2007 03:17:00 +0800</pubDate><guid>https://hessian.cn/p/649.html</guid><description>    一般来说输出函数都是在dll中。我们将详细介绍关于输出函数的各种结构，通过一个例子来说明输出函数及其相关结构是怎么放在PE文件中的。以及如何在PE文件中找到这些东西。</description></item><item><title>PE 格式学习总结（一）– PE文件概述</title><link>https://hessian.cn/p/328.html</link><pubDate>Wed, 18 Apr 2007 03:16:00 +0800</pubDate><guid>https://hessian.cn/p/328.html</guid><description>零 前言     PE格式，是Windows的可执行文件的格式。Windows中的 exe文件，dll文件，都是PE格式。PE 就是Portable Executable 的缩写。Portable 是指对于不同的Windows版本和不同的CPU类型上PE文件的格式是一样的，当然CPU不一样了，CPU指令的二进制编码是不一样的。只是文件中各种 东西的布局是一样的。&#10;</description></item><item><title>[转]visual c++对大型数据文件的读取</title><link>https://hessian.cn/p/401.html</link><pubDate>Wed, 18 Apr 2007 02:59:00 +0800</pubDate><guid>https://hessian.cn/p/401.html</guid><description>　笔者前不久曾遇到一个问题，解决之后的经验愿与大家分享。问题是这样的，有一批数据文件，数据格式如下：&#10;日期,开盘,最高,最低,收盘,成交量,成交金额 1996年5月13日,636.96,636.96,636.96,636.96,0,0,&#10;</description></item><item><title>用拷贝钩子实现对文件夹的监控</title><link>https://hessian.cn/p/579.html</link><pubDate>Wed, 18 Apr 2007 02:49:00 +0800</pubDate><guid>https://hessian.cn/p/579.html</guid><description>本文原出处已不知。原作：webber84， 经ccrun(老妖)修改并在BCB在调试通过。&#10;ICopyHook 是一个用于创建拷贝钩子处理程序COM接口，它决定一个文件夹或者打印机对象是否可以被移动，拷贝，重命名或删除。Shell在执行这些操作之前，会调用 ICopyHook接口的CopyCallback方法对它们进行验证。CopyCallback返回一个int值指示Shell是否应该继续执行这个操 作。返回值IDYES表示继续，而返回值IDNO和IDCANCEL则表示终止。&#10;</description></item><item><title>钩子的应用: 程序运行监视</title><link>https://hessian.cn/p/635.html</link><pubDate>Wed, 18 Apr 2007 02:48:00 +0800</pubDate><guid>https://hessian.cn/p/635.html</guid><description> 作者：Victor Chen&#10;来自：C++ 爱好者&#10;http://www.cppfans.com&#10;——————————————————————————–&#10;程序介绍:&#10;利用这个程序:&#10;1.可以监视在你的电脑运行的程序, 把在你的电脑运行过的程序的时间和名字记录下来;&#10;2.可以阻止你规定的禁用程序的执行, 比如不让玩游戏。&#10;3.这个程序需要加入注册表, 在系统启动时就运行, 达到监视的目的。注册表大概都不陌生，就是这里:&#10;HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionRun&#10;</description></item><item><title>软件看门狗–别让你的程序没有响应</title><link>https://hessian.cn/p/539.html</link><pubDate>Wed, 18 Apr 2007 02:48:00 +0800</pubDate><guid>https://hessian.cn/p/539.html</guid><description>原作者姓名 陆其明&#10;文章原始出处 http://hqtech.nease.net&#10;正文&#10;一．概述&#10;一些重要的程 序，必须让它一直跑着；而且还要时时关心它的状态——不能让它出现死锁现象。当然，如果一个主程序会出现死锁，肯定是设计或者编程上的失误。我们首要做的 事是，把这个Bug揪出来。但如果时间紧迫，这个Bug又“飘忽不定”，那么，我们还是先写一个软件“看门狗”，暂时应一下急吧。&#10;</description></item><item><title>Windows下DLL编程技术及应用</title><link>https://hessian.cn/p/523.html</link><pubDate>Wed, 18 Apr 2007 02:41:00 +0800</pubDate><guid>https://hessian.cn/p/523.html</guid><description>摘 要: 本文介绍了DLL技术在Windows编程中的基本运用方法及应用，给出了直接内存&#10;访问及端口I/O的两个实用DLL的全部源代码。&#10;关键词: DLL Windows编程 内存访问 I/O&#10;</description></item><item><title>在Windows桌面创建快捷方式</title><link>https://hessian.cn/p/598.html</link><pubDate>Wed, 18 Apr 2007 02:27:00 +0800</pubDate><guid>https://hessian.cn/p/598.html</guid><description>API提供了一个叫做IShellLink的COM接口允许我们创建快捷方式。为在桌面创建快捷方式，我们创建一个IShellLink对象，设置它的属性，然后把这个link保存到desktop目录。&#10;下面的例子代码演示了怎样创建一个快捷方式。在这个例子里，这个快捷方式保存在C:根目录下。&#10;//———————————————————————-&#10;#define NO_WIN32_LEAN_AND_MEAN&#10;#include &lt;shlobj.h&gt;&#10;#include &lt;vcl.h&gt;&#10;#pragma hdrstop&#10;</description></item><item><title>Visual C++中实现对图像数据的读取显示</title><link>https://hessian.cn/p/324.html</link><pubDate>Wed, 18 Apr 2007 02:21:00 +0800</pubDate><guid>https://hessian.cn/p/324.html</guid><description>在利用VC进行数据库编程时，经常需要处理数据库中的图像数据，将该图像从数据库中读取出来并显示，图像数据与 文本字段不同，它是作为OLE字段在数据库中存储，通过数据集对象的成员变量自动交换得到的图像数据，得到的数据并不能直接显示，如何处理图像数据，一直 是数据库编程中的一个难点，目前关于VC进行数据库编程的资料不少，但很少涉及图像数据的操作，笔者针对一现状，结合自己开发的一个项目，解决了如何显示 数据库中的图像这一问题，本文以操作ACESS数据库为例子，讲解一下自己的实现思路，希望对爱好VC编程的朋友们有所帮助，以起到抛砖引玉的作用。&#10;</description></item><item><title>几种VC++数据库开发技术的比较</title><link>https://hessian.cn/p/441.html</link><pubDate>Wed, 18 Apr 2007 02:21:00 +0800</pubDate><guid>https://hessian.cn/p/441.html</guid><description>　从功能简单的数据库(如Jet Engine)到复杂的大型数据库系统(如oracle)，VC++6.0都提供了一些编程接口。本文主要介绍以下五种:&#10;</description></item><item><title>Visual C++ 中的ODBC编程</title><link>https://hessian.cn/p/562.html</link><pubDate>Wed, 18 Apr 2007 02:20:00 +0800</pubDate><guid>https://hessian.cn/p/562.html</guid><description> ODBC（Open Database Connectivity，开放式数据库连接），是一种用来在相关或不相关的数据库管理系统（DBMS）中存取数据的标准应用程序接口（API）。本文给 出Windows 95 环境下用Visual C++ 进行ODBC 编程的具体方法及技巧。&#10;</description></item><item><title>利用Active X控件开发串口通信软件</title><link>https://hessian.cn/p/309.html</link><pubDate>Wed, 18 Apr 2007 02:18:00 +0800</pubDate><guid>https://hessian.cn/p/309.html</guid><description>　摘要：本文介绍了在Microsoft Visual C++ 6.0环境下通过对Active X控件的编程来实现串口的通信的一般方法。&#10;一、 引言&#10;当我们在Windows操作系统下开发串行通信程序时通常不得不面对许多复杂的API函数，因为在Windows操作系统下不能直接对设备端口进行操 作，也不能在系统级（Ring 3级别）使用任何DOS或BIOS中断，如要对端口进行编程则只能以文件的形式来对端口进行操作，这就使开发人员不得不面对非常烦琐的API函数编程。本 文对此提出了另外一种封装性很好的使用Microsoft Visual C++ 6.0自带的"Microsoft Communications Control，version 6.0"Active X控件的编程方法，通过对该控件的正确使用，我们可以比较轻松地编写出所需的串行通信程序。&#10;</description></item><item><title>通过COM技术实现Windows外壳编程</title><link>https://hessian.cn/p/373.html</link><pubDate>Wed, 18 Apr 2007 02:16:00 +0800</pubDate><guid>https://hessian.cn/p/373.html</guid><description>　摘要：本文介绍了一种有别于通常的Windows外壳编程方法。采用COM技术，通过Windows提供的外壳接口实现对其的编程。&#10;一、 引言&#10;在Windows环境下，不论是使用Visual C++还是Delphi或是其他一些软件开发工具，尽管存在着差别，但有一点是相同的：都是运行于Windows操作系统之下的。在程序开发过程中也经常 要在自己的应用程序中加入一些Windows系统本身就有的功能，比如文件的拷贝、删除、查找以及运行程序等等。而这些功能在Windows操作系统下都 是具备的，显然如果能直接从系统中调用这些功能将不仅仅减少程序的大小和开发人员的工作量，而且由于是直接通过操作系统来完成这些功能，将会大大减小这部 分程序出现异常错误的概率。Windows系统虽说也存在不少错误，但常用功能的错误还是比较少的，而且通过补丁程序可以更低限度减少系统错误，因此程序 员可以将调试检错的注意力放在应用程序的其他地方，对于调用系统功能这部分代码则可以不必投入太大的精力去调试，因为这部分调试的工作在操作系统发布的时 候就已经由微软做好了。&#10;</description></item><item><title>WinPcap 教程</title><link>https://hessian.cn/p/658.html</link><pubDate>Mon, 16 Apr 2007 04:58:00 +0800</pubDate><guid>https://hessian.cn/p/658.html</guid><description>原文出处：http://winpcap.polito.it/docs/man/html/index.html 作者: Loris Degioanni (degioanni@polito.it), NetGroup, Politecnico di Torino http://winpcap.polito.it 概述： 这 篇教程将会指引读者逐步了解WinPcap编程, 从简单的基础函数(获取网络接口列表, 捕捉数据包)到更高级的内容(处理发送队列, 网络流量统 计). 教程中包括一些代码片断, 以及一些简单但完整的例子, 读者可以参考这些例子更好的理解教程的内容. 这些例子全部用C语言写成, 所以基本的 C语言编程知识是必要. 同时, 因为这篇教程的内容是与底层网络紧密相连的, 所以笔者假设读者已经具备有关网络和协议的相关知识. 译者的话： WinPcap 是一套免费的, 基于Windows的网络接口API, 它在底层网络操作方面对程序员很有帮助. 这篇文档翻译自 "WinPcap Documentation 3.0" 中的 "WinPcap tutorial: a step by step guide to program WinPcap" 一部分. 这篇教程对初学者的帮助很大, 尤其是简短清晰的例 子, 但这篇教程只是整个文档的一小部分, 我认为你仍然需要参考文档的其它部分来了解各种结构等信息. 教程中注有前缀 "Y-" 的部分是译者为了让 读者更明白作者的意思添加的, 原文中没有. 1. 获取网络接口列表 通常, 一个基于WinPcap的应用程序所要做的第一件 事, 就是获得适合的网络接口的列表. Libpcap中的pcap_findalldevs()函数就是干这活的: 这个函数然回一个pcap_if结 构的列表, 每个元素都记录了一个接口的信息. 其中, name和description以人类可以阅读的形式, 记录了设备的信息. 下面的源代码输出可用的网络接口的列表, 并且在没有找到任何借口的情况下输出错误信息：</description></item><item><title>杀毒软件编程精华——特征码扫描技术</title><link>https://hessian.cn/p/551.html</link><pubDate>Mon, 16 Apr 2007 04:52:00 +0800</pubDate><guid>https://hessian.cn/p/551.html</guid><description>特征码扫描技术是反病毒技术中的常规武器，虽然特征码扫描技术有着一定的局限性，但是，改进的基于特征码扫描技术的广 谱特征串过滤技术却有着无比的优越性和广阔的应用前景。但是，无论是上面提到的哪种技术，最终都难以逃脱扫描算法的效率要求。而学过《数据结构》的读者应 该知道一种快速的字符串扫描算法叫做“模式匹配算法”，这种算法可以对字符串进行快速扫描。但是，深入进去就会发现，我们的特征码扫描算法中经常会用到通 配符，如：%和*（这里我令%匹配一个字符，*匹配32个字符），对于这样一些非常规的串，没有现成的算法可以引用。笔者在做防治木马技术的研究中，对常 规的模式匹配算法进行了改进，写出了如下的快速查找算法，暂且命名为“半回溯的模式匹配算法”，以与常规的“无回溯的模式匹配算法”区别。&#10;这里，我之所以称之为“半回溯”，就是因为在对通配符进行匹配时要进行适当的回溯，以减少因为采用通配符所带来的过长推进，虽然这是一种带有回溯的算法， 但是实际上它的效率并不比“无回溯的模式匹配算法”低多少，其对算法的效率不能构成真正的威胁。这个算法比较抽象，如果没有基础的读者最好先回头看一下 《数据结构》的教材中的“无回溯的模式匹配算法”，会对您接下来对算法的理解产生很大的帮助。光说不练，不是好汉，下面我们就开始艰辛而又刺激的模式匹配 算法之旅。&#10;对于“无回溯的模式匹配算法”，我不想做过多的说明，因为相关书籍上已经说得够明白了。下面，我们一起来看一下带通配符的半回溯的匹配算法（用%号匹配一个字符，用*匹配32个字符）：&#10;1.[初始化]&#10;i=1; j=1;&#10;counter1=0; counter2=0;&#10;2.[利用next[i]反复进行比较，直到i等于m+1]&#10;循环 当i&lt;=m且j&lt;=n时，反复执行&#10;若（p[i]!=’*’且p[i]==t[j]）&#10;则i=i+1; j=j+1; 否则若p[i]==’%’&#10;则 i=i+1; j=j+1; counter1=counter1+1;&#10;否则若p[i]==’*’&#10;则i=i+1; j=j+32; counter2=counter2+1;&#10;否则若next[i]&gt;0&#10;则i=next[i] j=j – (counter1+counter2*32);counter1=0;counter2=0;&#10;否则&#10;i=1; j=j – (counter1+counter2*32);j++;counter1=0;counter2=0;&#10;其中，counter1是用来统计%的个数，而counter2用来统计*的个数，其中m是子串的长度，n是被搜索串的长度。每次碰到子串中有%的时候就 自动将counter1加一，若是碰到counter2就自动将counter2加一。i用来指明子串的当前的比较的位置，而j用来指明被搜索串当前比较 的位置，如果一旦子串与被搜索串不能满足搜索条件，就要将被搜索串的比较位置进行回溯，以回到被通配符漏过的字符的个数，以便重新匹配。&#10;这里，涉及到了与“无回溯的模式匹配算法”中相同的要使用的Next数组，其中，Next数组的计算方法如下：&#10;1.[初始化]&#10;j=0; i=1;&#10;next[1]=0;&#10;2.[反复比较计算next[i+1]&#10;循环 当i&lt;m时，反复执行&#10;(1)[找出p1p2…pi中最大的相同的前缀和后缀，并将长度送j]&#10;循环 当j&gt;0且p[i]!=p[j] 且p[i]!=’%’且p[j]!=’%’时，反复执行&#10;j=next[j]&#10;(2)[计数器加1]&#10;i=i+1; j=j+1;&#10;(3)[计算next[i]]&#10;若p[i]==p[j]或p[i]==’%’或p[j]==’%’&#10;则next[i]=next[j];&#10;否则next[i]=j;&#10;Next数组的计算方法，与“无回溯匹配算法”稍有不同，因为%用来匹配一个字符，所以对于%的处理，可以看作比较的字符相等的情况来处理，而对*的比较，无论如何一个字符都不可能与一个32字符的字符串相等，所以对于*始终认为不相等。&#10;这个算法的描述，无论我作何解释，读者总会感觉到有一些抽象，而难于真正理解。下面，笔者写了一个简单的程序，来对这个算法进行测试，希望对您会有所帮 助。这个程序是在VC6.0的控制台下运行的，非常简单，基本上就上将以上的算法翻译成了C++语言。源程序可以在附书光盘中找到，名称为“带通配符的无 回溯模式匹配算法源程序”。&#10;在这个程序中，首先就是要建立一个子串和被搜索串，并确定算法中提到的m和n的值，如下所示。&#10;//被搜索的串&#10;char* t="nihaoaxishanchangshanchangaoyejiehhe*%dfisd%shanchashanchanghongioejw";&#10;//子串&#10;char* p="shanchang%*%hong";&#10;//next数组中元素的个数等于子串的长度&#10;int next[16];&#10;int i,j;&#10;//initialize variable&#10;j=0;i=1;next[0]=0;&#10;接下来，要计算next数组的值，对上面的算法进行翻译，得到如下代码。&#10;//计算next数组的循环&#10;while(i&lt;16)&#10;{&#10;while(j&gt;0&amp;&amp;p[i-1]!=p[j-1]&amp;&amp;p[i-1]!=’%’&amp;&amp;p[j-1]!=’%’)&#10;j=next[j-1];&#10;i++;&#10;j++;&#10;if(p[i-1]==p[j-1]||p[i-1]==’%’||p[j-1]==’%’)&#10;next[i-1]=next[j-1];&#10;else&#10;next[i-1]=j;&#10;}&#10;有了至关重要的next数组之后，就要使用改进了的模式匹配算法，从被搜索串中搜索出子串，代码如下：&#10;//模式匹配的循环&#10;i=1;&#10;j=1;&#10;int counter1=0,counter2=0;&#10;while(i&lt;=16&amp;&amp;j&lt;=69)&#10;{&#10;if(p[i-1]!=’*’&amp;&amp;p[i-1]==t[j-1])&#10;{i++;j++;}&#10;else if(p[i-1]==’%’)&#10;{&#10;i++;&#10;j++;&#10;counter1++;&#10;}&#10;else if (p[i-1]==’*’)&#10;{&#10;i++;&#10;j+=32;&#10;counter2++;&#10;}&#10;else if (next[i-1]&gt;0)&#10;{&#10;i=next[i-1];&#10;j-=(counter1+counter2*32);&#10;counter1=0;&#10;counter2=0;&#10;}&#10;else {&#10;i=1;&#10;j-=(counter1+counter2*32);&#10;j++;&#10;counter1=0;&#10;counter2=0;&#10;}&#10;//如果I等于17，说明对子串的搜索已经走到尽头，并搜索到了子串，跳出循环。&#10;if(i==17) break;&#10;}&#10;如果您需要使用这个算法进行特征码的查找，可以直接将其中的计算next数组和模式匹配的部分进行移植。&#10;到这里，基本上将要说的都说完了，可能您对这个算法还是有一些迷惑，如果您对其的正确性有疑问的话，可以使用上面的程序，对不同的子串和被搜索串进行操 作。另外，如果您对next数组不太了解，还是建议您找出教材来好好看一下。本算法的效率是比较高的，至于它的计算复杂度，我想在这里我就不能做过多的说 明了，有兴趣的读者，或者从事反病毒研究的读者，希望能对你们有一定的帮助，同时，如果有不对的地方，可以在黑防的论坛上面提一下，以期获得改进。&#10;后记：对于一个真正的程序员来说，其任务决不应该仅仅只是机械地拖拖控件，动动鼠标。更重要的应该是编程开始前的软件的整体安排和设计，而相关算法设计也 应该是非常重要的一部分。对于一个扫描软件来说，其扫描算法的设计也定是其精华所在。本文专门对算法进行相关分析，希望能够对您有所启发。&#10;</description></item><item><title>CGI扫描器的原理和实现过程</title><link>https://hessian.cn/p/395.html</link><pubDate>Sun, 15 Apr 2007 19:32:00 +0800</pubDate><guid>https://hessian.cn/p/395.html</guid><description>有很多网站为了安全起见，在WEB Server前面架了防火墙，或者做了TCP/IP过滤，对外只开放TCP 80 端口。从入侵者角度来看，要入侵那 么从80上跑的CGI入手是比较可行的，当然也可以用别的办法，例如旁敲侧击，呵呵。从网管角度来看，一是要保证CGI的安全性，另外网络的整体安全性也 是很重要的。针对基于80端口入侵、防范而出的CGI扫描器数不胜数，但基本上原理都一样。&#10;CGI扫描器原理说起来其实非常简单，可以用四句话来概括：&lt;1&gt;连接目标WEB SERVER；&lt;2&gt;发送一个特殊的请求；&lt;3&gt;接收目标服务器返回数据；&lt;4&gt;根据返回数据判断目标服务器是否有此CGI漏洞。&#10;当管理的服务器达到一定数量的时候，手工检测自己的服务器是否存在各种各样的CGI漏洞，那就太消耗时间和精力了，所以一个网管手上有个比较好用的 CGI漏洞扫描器还是必要的。OK！今天我们就自己来动手用C写一个简单的CGI扫描器，帮助自己在日常工作中检测服务器：））&#10;</description></item><item><title>用VC++编写CGI程序</title><link>https://hessian.cn/p/530.html</link><pubDate>Sun, 15 Apr 2007 18:58:00 +0800</pubDate><guid>https://hessian.cn/p/530.html</guid><description>近年来,Internet与Intranet迅猛发展,企业纷纷建立自己的Intranet,以加强企业内部的联系,促进与外部世界的沟通,增强企业的竞 争能力。通过建立自己的Internet服务器,企业能在网络上发布广告,介绍本公司的情况与产品,收集顾客意见,以及建立虚拟电子商场等。大家都知道写 一个HTML超文本文件放在World Wide Web服务器上,即可通过各种浏览器访问你的主页,但是如何使你的静态主页能响应客户的动作,并与本地的数据库联系,将数据库的相应内容传送给远端的浏览 器呢?这就需要通过CGI接口进行联系。&#10;CGI全名是Common Gateway Interface,它是WWW服务器调用外部程序的接口通过CGI,WW W服务器能完成一些本身所力不能及的工作。&#10;</description></item><item><title>Windows操作平台下CGI的实现</title><link>https://hessian.cn/p/364.html</link><pubDate>Sun, 15 Apr 2007 18:31:00 +0800</pubDate><guid>https://hessian.cn/p/364.html</guid><description>华中理工大学图像识别与人工智能研究所     龚建勇 实现WWW服务器与客户的交互可以有多种途径,如CGI、ISAPI、JAVA、ASP等,CGI是一种大家都比较熟悉的一种实现上述功能的有效途径,本文将就如何在Windows平台下实现CGI功能作一介绍。</description></item><item><title>病毒的本质</title><link>https://hessian.cn/p/609.html</link><pubDate>Fri, 13 Apr 2007 04:24:00 +0800</pubDate><guid>https://hessian.cn/p/609.html</guid><description>by Koms Bomb/CVC.GA 本文的目的，就是想说明写病毒其实是多么的容易。 一，病毒神话 我们先看看让大家“兴奋”、“激动”的病毒技术。 1，CIH，简直成了神话，CIH的作者也成为无数人的偶像。这神话，是AVer吹出来的，这偶像，只是中国人盲目崇拜的延续，外国人没这臭毛病。看看这个病毒里究竟有什么？1K多点的代码，再厉害能有什么？我觉得这个病毒唯一比较好的地方就是它的非常优化。这种优化，其实说白了也不难，只要稍微有些汇编编程经验，再加上一部指令手册（至少要有指令长度），再有足够的耐心，都可以做到。其它还有什么？进入Ring 0？早已有之，再说稍微懂些保护模式的人都知道利用GDT/IDT/LDT是可以进行特权转换的，常识问题。感染后文件大小不变？稍微了解PE格式的人都知道PE里有多少空地。使用VxD技术？Flash BIOS？只要能找到这些资料，有什么难的？VxD无非就是玩一些int 20h，Flash BIOS无非是写一些端口。调用中断，写端口，谁不会？但怎么调中断，写哪些端口，则需要知道相关的资料。我就写不出VxD为基础的病毒，我也不会Flash BIOS，因为我没有这方面的资料。 再看看时下“热门”的病毒技术。 2，跨平台病毒。跨Windows和Linux，同样是X86指令，有什么特殊的吗？基本上这种跨平台病毒，公用一部分变形之类的和OS无关的代码，而和OS有关的则是分开的。比如在Windows上就调用API，而在Linux上则用int 80h（没搞错中断号吧，我对Linux没什么研究）。其实就相当于两个病毒的合并。只要有了相关系统调用的资料，这种病毒显然很容易。其实写出针对不同CPU的病毒也不难，只要针对不同的文件感染不同的代码，然后把另外OS或CPU的代码做为数据不执行就行。顺便说一句，跨平台有什么用？有几个Linux机器上有PE文件的？又有几个Windows上有ELF文件的？ 3，.net病毒。有什么新鲜吗？Java不是也有病毒吗？只要掌握MSIL汇编，写一个真正的.net病毒并不难。值得一提的是前一阵炒得火热的两个.net病毒其实根本难登大雅之堂。29A的那个是用X86汇编写的，稍微有点头脑的都知道，.net是架构在MSIL上的，是一种中间语言，X86汇编根本就和.net无关。我没仔细看这个病毒的代码，但我估计无非是对EPE格式有一些不同于PE的操作，总体来说，还是PE病毒。那个“17岁天才少女”的C#病毒，算是.net病毒吧，但值得一吹吗？你，说的就是你，去看看C#语法，再略微看一些.net framework，相信你也可以用C#写出一个可以把自己通过邮件发出去的程序，这就是时髦的.net病毒。 4，metamorphism。简直被AVer吹上天了。这东西说白了其实就是对自身代码进行重新编码。过程是，反汇编自己的代码，重新改写（比如mov eax,esi可以写成push esi;pop eax等等），插入垃圾代码。当然最好还要在下一代中删除垃圾代码。怎样判断垃圾代码？显然看到一条指令的目的操作数在以后没有被当作源操作数，就可以认为是垃圾。这东西玩弄的是机器代码技巧，只要在手边摆一部Intel的指令手册，再加上足够的耐心，想对代码重新编码，不难。但写这东西确实很繁琐，可以说是非常繁琐，写出的代码也很大，没有实用价值。以后有空我可能会重新考虑一个semi-metamorphism，也不难，但力求小，如果engine超过8K，我将放弃。</description></item><item><title>向其他进程注入代码的三种方法[1]</title><link>https://hessian.cn/p/529.html</link><pubDate>Fri, 13 Apr 2007 03:44:00 +0800</pubDate><guid>https://hessian.cn/p/529.html</guid><description>     本文章翻译自Robet Kuster的Three Ways to Inject Your Code into Another Process一文，原版地址见下面。本文章版权归原作者所有。&#10;     如果转载该译文,请保证文章的完整性，并注明来自www.farproc.com&#10;袁晓辉   &#10;2005/5/20&#10;</description></item><item><title>向其他进程注入代码的三种方法[2]</title><link>https://hessian.cn/p/305.html</link><pubDate>Fri, 13 Apr 2007 03:44:00 +0800</pubDate><guid>https://hessian.cn/p/305.html</guid><description>     这是什么意思？每个进程都有一个特殊的寄存器，这个寄存器指向下一条要执行的指令的内存地址，即32位Intel和AMD处理器上所谓的EIP寄存器。因为EIP是个特殊的寄存器，所以你不能像访问通用寄存器（EAX，EBX等）那样来访问它。换句话说，你找不到一个可以用来寻址EIP并且对它进行读写的操作码（OpCode）。然而，EIP同样可以被JMP，CALL，RET等指令隐含地改变（事实上它一直都在改变）。让我们举例说明32位的Intel和AMD处理器上CALL/RET是如何工作的吧：&#10;</description></item><item><title>windows C语言网络编程快速入门</title><link>https://hessian.cn/p/486.html</link><pubDate>Tue, 10 Apr 2007 15:01:00 +0800</pubDate><guid>https://hessian.cn/p/486.html</guid><description>Windows下C语言网络编程快速入门&#10;   C语言的学习，一般的方式是，先学C，然后是C++，最好还要有汇编语言和微机原理基础，然后才是Visual C++。这样的方式，对学习者来说，要花费很多时间和耐力。而在学校教学中，也没有时间深入学习Windows编程的实用技术了。&#10;</description></item><item><title>VC小技巧15则</title><link>https://hessian.cn/p/493.html</link><pubDate>Mon, 09 Apr 2007 21:13:00 +0800</pubDate><guid>https://hessian.cn/p/493.html</guid><description>一、 一次只运行一个程序实例&#10;下列两种方式都可以实现，建议采用第二种方式：&#10;1、 if( FindWindow(NULL,"程序标题"))          exit(0);&#10;2、BOOL CDemoTBarEApp::InstanceIsRun()&#10;{&#10;HANDLE m_hMutex;&#10;m_hMutex = ::CreateMutex(NULL, TRUE, _T("YourApplication"));&#10;ASSERT(m_hMutex);&#10;if (GetLastError() == ERROR_ALREADY_EXISTS)&#10;{&#10;m_hMutex = NULL;&#10;return TRUE;//实例已经运行&#10;}&#10;return FALSE;//实例未运行&#10;}&#10;</description></item><item><title>BC++B 可视化组件库VCL中的对象、组件与控件</title><link>https://hessian.cn/p/531.html</link><pubDate>Sat, 07 Apr 2007 14:53:00 +0800</pubDate><guid>https://hessian.cn/p/531.html</guid><description>     图2 – 1为可视组件库的分层结构的简图，图中显示出了树状分层结构的五个主要的分支。&#10;2.4.1 TObject分支&#10;     下面几部分分别对包含于五个主要分支中的类做出简要地描述，为完整地说明VCL对象的分层结构，引用了包含于产品中的VCL对象分层结构图。&#10;     所有的VCL对象都派生于TObject，其方法定义了构造、析构、消息处理等基本特征。VCL对象的许多强大的功能都建立在TObject给出的这些方法的基础之上。通过提供下列方法，TObject封装了所有VCL对象最基本的通用特征：&#10;· 在对象被创建或销毁时响应的能力。&#10;· 对象的类型和实例信息，及有关对象发布的属性的运行时类型信息（RTTI）&#10;· 支持消息处理。&#10;     TObject是许多简单类的直接祖先。在这一分支中所包含的类有一个共同的重要的特性，它们都是暂时的。这是指，这些类都没有用来在对象被销毁之前保存状态的方法，它们不是固有的。&#10;     在这一分支中一个较主要的类为异常（Exception）类。它提供一组内嵌的异常类用于自动处理除数为零的错误、文件I/O错误、非法的类型匹配及许多其他的异常情况。&#10;     包含于TObject分支的还有一些封装数据结构的类，例如：&#10;· TBits，存储了一个布尔型“数组”的类。&#10;· TList，链接列表的类。&#10;· TStack ，包含一个“后进先出”的指针数组的类。&#10;· TQueue，包含一个“先进先出”的指针数组的类。&#10;     此外，你还可以发现一些封装了外部对象的类，如TPrinter，它封装了Windows打印机接口，TRegistry，它封装了底层系统注册及其函数。&#10;     TStream是这一分支里其他类型的典型例子。TStream是流对象的基类，可以与如磁盘文件、动态内存等等各种存储介质进行读写操作。&#10;     可以看到，这一分支中包含许多不同类，对于一个开发者来说，这些类都非常有用。&#10;</description></item><item><title>C++ string(字符串)详解</title><link>https://hessian.cn/p/483.html</link><pubDate>Sat, 07 Apr 2007 14:53:00 +0800</pubDate><guid>https://hessian.cn/p/483.html</guid><description>好了，进入正题………&#10;首先，为了在我们的程序中使用string类型，我们必须包含头文件 。如下：&#10;＃i nclude&lt;string&gt; //注意这里不是string.h string.h是C字符串头文件&#10;</description></item><item><title>VCL库函数</title><link>https://hessian.cn/p/318.html</link><pubDate>Sat, 07 Apr 2007 14:53:00 +0800</pubDate><guid>https://hessian.cn/p/318.html</guid><description> //—————————– Suntenghe 整理——————–&#10;1.内存分配&#10;2.文件操作&#10;3.磁盘目录管理&#10;4.字符串操作&#10;5.类型转换&#10;6.时间和日期管理&#10;</description></item><item><title>10年编程无师自通</title><link>https://hessian.cn/p/320.html</link><pubDate>Sat, 07 Apr 2007 14:51:00 +0800</pubDate><guid>https://hessian.cn/p/320.html</guid><description>原文：Teach Yourself Programming in Ten Years&#10;作者：Peter Norvig&#10;翻译：郭晓刚（foosleeper@163.net）&#10;最后修订日期：2004-3-19&#10;2005-01-12增加了新的译本链接。&#10;</description></item><item><title>优秀IT书籍100本</title><link>https://hessian.cn/p/640.html</link><pubDate>Sat, 07 Apr 2007 14:51:00 +0800</pubDate><guid>https://hessian.cn/p/640.html</guid><description>1.vc++技术内幕第四版 (潘爱民) ftp://210.32.157.56/课件/c++primer/vc++技术内幕IV(潘爱民).rar 2.C++经典对话系列 中文：http://www.jka77.com/book/cvst_cn.chm</description></item><item><title>C中const的使用</title><link>https://hessian.cn/p/576.html</link><pubDate>Sat, 07 Apr 2007 14:49:00 +0800</pubDate><guid>https://hessian.cn/p/576.html</guid><description> 基本解释&#10;const是一个C语言的关键字，它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的健壮性，另外，在观看别人代码的时候，清晰理解const所起的作用，对理解对方的程序也有一些帮助。&#10;虽然这听起来很简单，但实际上，const的使用也是c语言中一个比较微妙的地方，微妙在何处呢？请看下面几个问题。&#10;问题：const变量 &amp; 常量&#10;为什么我象下面的例子一样用一个const变量来初始化数组，ANSI C的编译器会报告一个错误呢？&#10;const int n = 5;&#10;int a[n]; 答案与分析:&#10;1）、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的，例如5， “abc”，等，肯定是只读的，因为程序中根本没有地方存放它的值，当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值，只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符（Qualifier）。上述代码中变量n被修饰为只读变量，可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”，“只读变量”也是不可以的。&#10;2)、注意：在ANSI C中，这种写法是错误的，因为数组的大小应该是个常量，而const int n,n只是一个变量（常量 != 不可变的变量，但在标准C++中，这样定义的是一个常量，这种写法是对的），实际上，根据编译过程及内存分配来看，这种用法本来就应该是合理的，只是ANSI C对数组的规定限制了它。&#10;3)、那么，在ANSI C 语言中用什么来定义常量呢？答案是enum类型和#define宏，这两个都可以用来定义常量。 问题：const变量 &amp; const 限定的内容&#10;下面的代码编译器会报一个错误，请问，哪一个语句是错误的呢？&#10;typedef char * pStr;&#10;char string[4] = "abc";&#10;const char *p1 = string;&#10;const pStr p2 = string;&#10;p1++;&#10;p2++; 答案与分析：&#10;问题出在p2++上。&#10;1)、const使用的基本形式： const char m; 限定m不可变。&#10;2)、替换1式中的m, const char *pm; 限定*pm不可变，当然pm是可变的，因此问题中p1++是对的。&#10;3)、替换1式char, const newType m; 限定m不可变，问题中的charptr就是一种新类型，因此问题中p2不可变，p2++是错误的。&#10;问题：const变量 &amp; 字符串常量&#10;请问下面的代码有什么问题？&#10;char *p = "i’m hungry!";&#10;p[0]= ‘I’; 答案与分析：&#10;上面的代码可能会造成内存的非法写操作。分析如下， “i’m hungry”实质上是字符串常量，而常量往往被编译器放在只读的内存区，不可写。p初始指向这个只读的内存区，而p[0] = ‘I’则企图去写这个地方，编译器当然不会答应。&#10;问题：const变量 &amp; 字符串常量2&#10;请问char a[3] = "abc" 合法吗？使用它有什么隐患？ 答案与分析：&#10;在标准C中这是合法的，但是它的生存环境非常狭小；它定义一个大小为3的数组，初始化为“abc”，，注意，它没有通常的字符串终止符”，因此这个数组只是看起来像C语言中的字符串，实质上却不是，因此所有对字符串进行处理的函数，比如strcpy、printf等，都不能够被使用在这个假字符串上。&#10;问题5：const &amp; 指针&#10;类型声明中const用来修饰一个常量，有如下两种写法，那么，请问，下面分别用const限定不可变的内容是什么?&#10;1)、const在前面&#10;const int nValue； //nValue是const&#10;const char *pContent; //*pContent是const, pContent可变&#10;const (char *) pContent;//pContent是const,*pContent可变&#10;char* const pContent; //pContent是const,*pContent可变&#10;const char* const pContent; //pContent和*pContent都是const 2)、const在后面，与上面的声明对等&#10;int const nValue； // nValue是const&#10;char const * pContent;// *pContent是const, pContent可变&#10;(char *) const pContent;//pContent是const,*pContent可变&#10;char* const pContent;// pContent是const,*pContent可变&#10;char const* const pContent;// pContent和*pContent都是const 答案与分析：&#10;const和指针一起使用是C语言中一个很常见的困惑之处，在实际开发中，特别是在看别人代码的时候，常常会因为这样而不好判断作者的意图，下面讲一下我的判断原则：&#10;沿着*号划一条线，如果const位于*的左侧，则const就是用来修饰指针所指向的变量，即指针指向为常量；如果const位于*的右侧，const就是修饰指针本身，即指针本身是常量。你可以根据这个规则来看上面声明的实际意义，相信定会一目了然。&#10;另外，需要注意：对于const (char *) ; 因为char *是一个整体，相当于一个类型(如 char)，因此，这是限定指针是const。 另＝＝＝＝＝＝＝&#10;const用于函数时出现三个位置:&#10;例如:&#10;const returnVal   function (const list_array)const;&#10;形式不过如此&#10;第一个const意思是:返回值是常量&#10;第二个const意思是:函数过程中不能修改list_array的值&#10;第三个const意思是:函数过程不能隐式的修改function参数的值&#10;＝＝＝&#10;const char*, char const*, char*const的区别问题几乎是C++面试中每次都会有的题目。 事实上这个概念谁都有只是三种声明方式非常相似很容易记混。 Bjarne在他的The C++ Programming Language里面给出过一个助记的方法： 把一个声明从右向左读。 char * const cp; ( * 读成 pointer to ) cp is a const pointer to char const char * p; p is a pointer to const char; char const * p; 同上因为C++里面没有const*的运算符，所以const只能属于前面的类型。 另:下面定义的一个指向字符串的常量指针： char * const prt1 = stringprt1; 其中，ptr1是一个常量指针。因此，下面赋值是非法的。 ptr1 = stringprt2; 而下面的赋值是合法的： *ptr1 = "m"; 因为指针ptr1所指向的变量是可以更新的，不可更新的是常量指针ptr1所指的方向(别的字符串)。&#10;下面定义了一个指向字符串常量的指针： const * ptr2 = stringprt1; 其中，ptr2是一个指向字符串常量的指针。ptr2所指向的字符串不能更新的，而ptr2是可以更新的。因此， *ptr2 = "x"; 是非法的，而： ptr2 = stringptr2; 是合法的。 所以，在使用const修饰指针时，应该注意const的位置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时，const修饰符的位置不同，前者const放在*和指针名之间，后者const放在类型说明符前。&#10;</description></item><item><title>[转]TCP/IP 网络基础(v 0.2b)</title><link>https://hessian.cn/p/392.html</link><pubDate>Sat, 07 Apr 2007 14:46:00 +0800</pubDate><guid>https://hessian.cn/p/392.html</guid><description>作者：北南南北&#10;来自：LinuxSir.Org&#10;赞助： pandonny、etony、Linuxfish ……..&#10;简介：本文简要的讲了讲TCP/IP的一点基础，包括TCP/IP网络模型；网络分类及切割，以及服务和端口等基础知识；需要声明的是，我并不懂TCP/IP的原理，我只是写一点比较表面的东西。&#10;</description></item><item><title>解析C语言复杂声明</title><link>https://hessian.cn/p/399.html</link><pubDate>Sat, 07 Apr 2007 14:39:00 +0800</pubDate><guid>https://hessian.cn/p/399.html</guid><description>C语言所有复杂的指针声明，都是由各种声明嵌套构成的。如何解读复杂指针声明呢？右左法则是一个既著名又常用的方法。不过，右左法则其实并不是C标准里面的内容，它是从C标准的声明规定中归纳出来的方法。C标准的声明规则，是用来解决如何创建声明的，而右左法则是用来解决如何辩识一个声明的，两者可以说是相反的。右左法则的英文原文是这样说的：&#10;</description></item><item><title>关于(*(void(*)())0)()</title><link>https://hessian.cn/p/622.html</link><pubDate>Sat, 07 Apr 2007 14:38:00 +0800</pubDate><guid>https://hessian.cn/p/622.html</guid><description>    前段时间看了这本C Traps and Pitfalls，看到里面有这样的一个语句：&#10;   (*(void(*)())0)();&#10;    初看此语句，让我头皮发麻，不寒而栗呀，我看了好半天书，也只是一知半解，后来在下面两个论坛上分别发一个帖子问了一下：&#10;http://bbs.chinaunix.net/viewthread.php?tid=891271&amp;extra=page%3D2&#10;http://www.vckbase.com/bbs/viewtopic2.asp?rid=2869084&amp;sf=92&amp;forumID=1&amp;pg=4&#10;</description></item><item><title>C语言全局变量和局部变量</title><link>https://hessian.cn/p/448.html</link><pubDate>Sat, 07 Apr 2007 14:29:00 +0800</pubDate><guid>https://hessian.cn/p/448.html</guid><description>引子—&#10;         变量可以在程序中三个地方说明: 函数内部、函数的参数定义中或所有的函数外部。根据所定义位置的不同, 变量可分为局部变量、形式参数和全程变量。从空间角度来看，变量可以分为全局变量和局部变量，而从时间角度来分的 可以有静态存储变量和动态存储变量之分。&#10;</description></item><item><title>实现C语言高效编程的四大秘技</title><link>https://hessian.cn/p/499.html</link><pubDate>Sat, 07 Apr 2007 14:29:00 +0800</pubDate><guid>https://hessian.cn/p/499.html</guid><description>第1招：以空间换时间&#10;计算机程序中最大的矛盾是空间和时间的矛盾，那么，从这个角度出发逆向思维来考虑程序的效率问题，我们就有了解决问题的第1招——以空间换时间。&#10;</description></item><item><title>系统钩子和DLL</title><link>https://hessian.cn/p/584.html</link><pubDate>Sat, 07 Apr 2007 14:28:00 +0800</pubDate><guid>https://hessian.cn/p/584.html</guid><description>系统钩子和DLL&#10;钩子的本质是一段用以处理系统消息的程序，通过系统调用，将其挂入系统。钩子的种类有很多，每种钩子可以截获并处理相应的消息，每当特定的消息发出，在到 达目的窗口之前，钩子程序先行截获该消息、得到对此消息的控制权。此时在钩子函数中就可以对截获的消息进行加工处理，甚至可以强制结束消息的传递。&#10;在本程序中我们需要捕获在任意窗口上的键盘输入，这就需要采用全局钩子以便拦截整个系统的消息，而全局钩子函数必须以DLL（动态连接库）为 载体进行封装，VC6中有三种形式的MFC DLL可供选择，即Regular statically linked to MFC DLL（标准静态链接MFC DLL）、Regular using the shared MFC DLL（标准动态链接MFC DLL）以及Extension MFC DLL（扩展MFC DLL）。 在本程序中为方便起见采用了标准静态连接MFC DLL。&#10;三、键盘钩子程序示例&#10;本示例程序用到全局钩子函数，程序分两部分：可执行程序KeyHook和动态连接库LaunchDLL。&#10;1、首先编制MFC扩展动态连接库LaunchDLL.dll:&#10;（1）选择MFC AppWizard(DLL)创建项目LaunchDLL；在接下来的选项中选择Regular statically linked to MFC DLL（标准静态链接MFC DLL）。&#10;（2）在LaunchDLL.h中添加宏定义和待导出函数的声明：&#10;#define DllExport __declspec(dllexport)&#10;……&#10;DllExport void WINAPI InstallLaunchEv();&#10;……&#10;class CLaunchDLLApp : public CWinApp&#10;{&#10;public:&#10;CLaunchDLLApp();&#10;</description></item><item><title>用BCB在windows桌面创建快捷方式</title><link>https://hessian.cn/p/384.html</link><pubDate>Thu, 05 Apr 2007 23:34:00 +0800</pubDate><guid>https://hessian.cn/p/384.html</guid><description>API提供了一个叫做IShellLink的COM接口允许我们创建快捷方式。为在桌面创建快捷方式，我们创建一个IShellLink对象，设置它的属性，然后把这个link保存到desktop目录。 下面的例子代码演示了怎样创建一个快捷方式。在这个例子里，这个快捷方式保存在C:Drive目录下。 //———————————————————————- include &lt;shlobj.h&gt; void __fastcall TForm1::Button1Click(TObject *Sender) { if(OpenDialog1-&gt;Execute()) CreateShortCut(OpenDialog1-&gt;FileName); } //———————————————————————- void TForm1::CreateShortCut(const AnsiString &amp;file) { IShellLink* pLink; IPersistFile* pPersistFile; if(SUCCEEDED(CoInitialize(NULL))) { if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &amp;pLink))) { pLink-&gt;SetPath(file.c_str()); pLink-&gt;SetDescription(“Woo hoo, look at Homer“s shortcut“); pLink-&gt;SetShowCmd(SW_SHOW); if(SUCCEEDED(pLink-&gt;QueryInterface(IID_IPersistFile, (void **)&amp;pPersistFile))) { WideString strShortCutLocation(“C:\bcbshortcut.lnk“); pPersistFile-&gt;Save(strShortCutLocation.c_bstr(), TRUE); pPersistFile-&gt;Release(); } pLink-&gt;Release(); } CoUninitialize(); } } //———————————————————————- 上面的例子只是把快捷方式文件保存到了c:drive目录下，但没保存到desktop目录下。 要让快捷方式出现在桌面上，只须把快捷方式文件保存到desktop目录下。首先我们要找到windows的desktop目录，请参阅判断 windows的Desktop及相关目录这一节。一旦我们知道了desktop所在的目录，我们就能将快捷方式文件保存到desktop目录下。然后 windows就能将快捷方式图标显示到桌面上。下面是经过改进了的例子： //———————————————————————- void TForm1::CreateShortCut(const AnsiString &amp;file) { IShellLink* pLink; IPersistFile* pPersistFile; LPMALLOC ShellMalloc; LPITEMIDLIST DesktopPidl; char DesktopDir[MAX_PATH]; if(FAILED(SHGetMalloc(&amp;ShellMalloc))) return; if(FAILED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &amp;DesktopPidl))) return; if(!SHGetPathFromIDList(DesktopPidl, DesktopDir)) { ShellMalloc-&gt;Free(DesktopPidl); ShellMalloc-&gt;Release(); return; } ShellMalloc-&gt;Free(DesktopPidl); ShellMalloc-&gt;Release(); if(SUCCEEDED(CoInitialize(NULL))) { if(SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &amp;pLink))) { pLink-&gt;SetPath(file.c_str()); pLink-&gt;SetDescription(“Woo hoo, look at Homer“s shortcut“); pLink-&gt;SetShowCmd(SW_SHOW); if(SUCCEEDED(pLink-&gt;QueryInterface(IID_IPersistFile, (void **)&amp;pPersistFile))) { WideString strShortCutLocation(DesktopDir); strShortCutLocation += “\bcbshortcut.lnk“; pPersistFile-&gt;Save(strShortCutLocation.c_bstr(), TRUE); pPersistFile-&gt;Release(); } pLink-&gt;Release(); } CoUninitialize(); } } //———————————————————————- 不要陷于COM的泥沼之中 创建快捷方式包括一些对COM的使用。不要让你陷入到COM的复杂之中。COM只是创建和使用对象的一种方法。在这个例子里我们可以考虑不使用COM而是用等价的C++技术。 COM code C++ psuedo-equivalent IShellLink* pLink; TShellLink *Link; IPersistFile* pPersistFile; TPersistFile *PersistFile; CoInitialize();</description></item><item><title>堆和栈的区别</title><link>https://hessian.cn/p/343.html</link><pubDate>Thu, 05 Apr 2007 21:28:00 +0800</pubDate><guid>https://hessian.cn/p/343.html</guid><description>作者: 芊珑发布日期: 2006-2-10 查看数: 125 出自: http://www.cnitexam.com 一、预备知识—程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分 1、栈区（stack）— 由编译器自动分配释放 ，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区（heap） — 一般由程序员分配释放， 若程序员不释放，程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事，分配方式倒是类似于链表，呵呵。 3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域， 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 – 程序结束后有系统释放 4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 5、程序代码区—存放函数体的二进制代码。</description></item><item><title>联高软件：BCB编程经验几则</title><link>https://hessian.cn/p/312.html</link><pubDate>Thu, 05 Apr 2007 21:25:00 +0800</pubDate><guid>https://hessian.cn/p/312.html</guid><description>问：怎么实现TRichEdit的自动滚行？象某些阅读器那样的功能。 答：用ScrollWindowEx或者ScrollWindowEx就可以了。 ScrollWindow(RichEdit1- &gt;Handle, 0, -1, NULL, NULL); //向下滚1个像素 ScrollWindow(RichEdit1- &gt;Handle, 0, 1, NULL, NULL); //向上滚1个像素</description></item></channel></rss>