﻿<?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>C++博客-C++-----勇者无敌</title><link>http://www.cppblog.com/limk/</link><description>流媒体、分布式实时系统、外挂、设计模式、C#</description><language>zh-cn</language><lastBuildDate>Sun, 05 Apr 2026 22:38:32 GMT</lastBuildDate><pubDate>Sun, 05 Apr 2026 22:38:32 GMT</pubDate><ttl>60</ttl><item><title>C++数据类型与C#对应关系</title><link>http://www.cppblog.com/limk/archive/2008/07/30/57531.html</link><dc:creator>李明坤</dc:creator><author>李明坤</author><pubDate>Wed, 30 Jul 2008 09:14:00 GMT</pubDate><guid>http://www.cppblog.com/limk/archive/2008/07/30/57531.html</guid><wfw:comment>http://www.cppblog.com/limk/comments/57531.html</wfw:comment><comments>http://www.cppblog.com/limk/archive/2008/07/30/57531.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/limk/comments/commentRss/57531.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/limk/services/trackbacks/57531.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td>
            <p>C++&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输入输出&nbsp;&nbsp;&nbsp; C# <br>==================================<br>char chr[255]&nbsp;&nbsp; O&nbsp;&nbsp;&nbsp; StringBuilder<br>KCA_DIR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; int<br>LPCSTR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; string<br>int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; int<br>LPSTR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O&nbsp;&nbsp;&nbsp; StringBuilder<br>int*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O&nbsp;&nbsp;&nbsp; out int<br>DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; int<br>DWORD*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O&nbsp;&nbsp;&nbsp; out int<br>BOOL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; bool<br>Rc_DBMgr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I&nbsp;&nbsp;&nbsp; IntPtr<br>long*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O&nbsp;&nbsp;&nbsp; out long</p>
            </td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p>
<table cellPadding=1 width=600 bgColor=#666666 border=0>
    <tbody>
        <tr>
            <td bgColor=#ffffff colSpan=6>
            <div align=center>API与C#的数据类型对应关系表</div>
            </td>
        </tr>
        <tr>
            <td bgColor=#ffffff>API数据类型</td>
            <td bgColor=#ffffff>类型描述</td>
            <td bgColor=#ffffff>C#类型</td>
            <td bgColor=#ffffff>API数据类型</td>
            <td bgColor=#ffffff>类型描述</td>
            <td bgColor=#ffffff>C#类型</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>WORD</td>
            <td bgColor=#ffffff>16位无符号整数</td>
            <td bgColor=#ffffff>ushort</td>
            <td bgColor=#ffffff>CHAR</td>
            <td bgColor=#ffffff>字符</td>
            <td bgColor=#ffffff>char</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>LONG</td>
            <td bgColor=#ffffff>32位无符号整数</td>
            <td bgColor=#ffffff>int</td>
            <td bgColor=#ffffff>DWORDLONG</td>
            <td bgColor=#ffffff>64位长整数</td>
            <td bgColor=#ffffff>long</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>DWORD</td>
            <td bgColor=#ffffff>32位无符号整数</td>
            <td bgColor=#ffffff>uint</td>
            <td bgColor=#ffffff>HDC</td>
            <td bgColor=#ffffff>设备描述表句柄</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>HANDLE</td>
            <td bgColor=#ffffff>句柄,32位整数</td>
            <td bgColor=#ffffff>int</td>
            <td bgColor=#ffffff>HGDIOBJ</td>
            <td bgColor=#ffffff>GDI对象句柄</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>UINT</td>
            <td bgColor=#ffffff>32位无符号整数</td>
            <td bgColor=#ffffff>uint</td>
            <td bgColor=#ffffff>HINSTANCE</td>
            <td bgColor=#ffffff>实例句柄</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>BOOL</td>
            <td bgColor=#ffffff>32位布尔型整数</td>
            <td bgColor=#ffffff>bool</td>
            <td bgColor=#ffffff>HWM</td>
            <td bgColor=#ffffff>窗口句柄</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>LPSTR</td>
            <td bgColor=#ffffff>指向字符的32位指针</td>
            <td bgColor=#ffffff>string</td>
            <td bgColor=#ffffff>HPARAM</td>
            <td bgColor=#ffffff>32位消息参数</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>LPCSTR</td>
            <td bgColor=#ffffff>指向常字符的32位指针</td>
            <td bgColor=#ffffff>String</td>
            <td bgColor=#ffffff>LPARAM</td>
            <td bgColor=#ffffff>32位消息参数</td>
            <td bgColor=#ffffff>int</td>
        </tr>
        <tr>
            <td bgColor=#ffffff>BYTE</td>
            <td bgColor=#ffffff>字节</td>
            <td bgColor=#ffffff>byte</td>
            <td bgColor=#ffffff>WPARAM</td>
            <td bgColor=#ffffff>32位消息参数</td>
            <td bgColor=#ffffff>int</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p>
<table cellSpacing=0 cellPadding=0 border=0>
    <tbody>
        <tr>
            <td vAlign=top width="24%">
            <p align=center><strong><span>Wtypes.h </span></strong><strong><span>中的非托管类型</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p align=center><strong><span>非托管</span><span> C </span></strong><strong><span>语言类型</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p align=center><strong><span>托管类名</span></strong></p>
            </td>
            <td vAlign=top width="24%">
            <p align=center><strong><span>说明</span></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>HANDLE</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>void*</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.IntPtr</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>BYTE</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>unsigned char</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Byte</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>8 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>SHORT</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>short</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Int16</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>16 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>WORD</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>unsigned short</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.UInt16</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>16 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>INT</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>int</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Int32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>UINT</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>unsigned int</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.UInt32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>LONG</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>long</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Int32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>BOOL</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>long</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Int32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>DWORD</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>unsigned long</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.UInt32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>ULONG</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>unsigned long</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.UInt32</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>CHAR</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>char</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Char</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>用</span><span> ANSI </span><span>修饰。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>LPSTR</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>char*</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.String </span><span>或</span><span> System.StringBuilder</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>用</span><span> ANSI </span><span>修饰。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>LPCSTR</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>Const char*</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.String </span><span>或</span><span> System.StringBuilder</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>用</span><span> ANSI </span><span>修饰。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>LPWSTR</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>wchar_t*</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.String </span><span>或</span><span> System.StringBuilder</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>用</span><span> Unicode </span><span>修饰。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>LPCWSTR</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>Const wchar_t*</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.String </span><span>或</span><span> System.StringBuilder</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>用</span><span> Unicode </span><span>修饰。</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>FLOAT</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>Float</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Single</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>32 </span><span>位</span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width="24%">
            <p><strong><span>DOUBLE</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><strong><span>Double</span></strong></p>
            </td>
            <td vAlign=top width="26%">
            <p><span>System.Double</span></p>
            </td>
            <td vAlign=top width="24%">
            <p><span>64 </span><span>位</span></p>
            </td>
        </tr>
    </tbody>
</table>
</p><img src ="http://www.cppblog.com/limk/aggbug/57531.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/limk/" target="_blank">李明坤</a> 2008-07-30 17:14 <a href="http://www.cppblog.com/limk/archive/2008/07/30/57531.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#操作INI类</title><link>http://www.cppblog.com/limk/archive/2008/07/30/57530.html</link><dc:creator>李明坤</dc:creator><author>李明坤</author><pubDate>Wed, 30 Jul 2008 09:10:00 GMT</pubDate><guid>http://www.cppblog.com/limk/archive/2008/07/30/57530.html</guid><wfw:comment>http://www.cppblog.com/limk/comments/57530.html</wfw:comment><comments>http://www.cppblog.com/limk/archive/2008/07/30/57530.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/limk/comments/commentRss/57530.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/limk/services/trackbacks/57530.html</trackback:ping><description><![CDATA[<p><span style="COLOR: rgb(0,0,255)">using</span><span style="COLOR: rgb(0,0,0)"> System; <br></span><span style="COLOR: rgb(0,0,255)">using</span><span style="COLOR: rgb(0,0,0)"> System.IO; <br></span><span style="COLOR: rgb(0,0,255)">using</span><span style="COLOR: rgb(0,0,0)"> System.Runtime.InteropServices; <br></span><span style="COLOR: rgb(0,0,255)">using</span><span style="COLOR: rgb(0,0,0)"> System.Text;<br><br><br></span><span style="COLOR: rgb(0,0,255)">namespace</span><span style="COLOR: rgb(0,0,0)"> OperateIni<br>{<br></span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">class</span><span style="COLOR: rgb(0,0,0)"> IniFile<br>{ <br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> IniFileName; <br><br>&nbsp;&nbsp; [DllImport(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">kernel32</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)] <br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">extern</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> GetPrivateProfileInt(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpAppName, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpKeyName, <br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> nDefault, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpFileName); <br><br>&nbsp;&nbsp; [DllImport(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">kernel32</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)] <br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">extern</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> GetPrivateProfileString(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpAppName, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpKeyName, <br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpDefault, StringBuilder lpReturnedString, </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> nSize, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpFileName); <br><br>&nbsp;&nbsp; [DllImport(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">kernel32</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">)] <br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">private</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">static</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">extern</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">bool</span><span style="COLOR: rgb(0,0,0)"> WritePrivateProfileString(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpAppName, <br>&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpKeyName, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpString, </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> lpFileName); <br><br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> IniFile(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Filename) <br>&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IniFileName </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> Filename; <br>&nbsp;&nbsp; } <br>&nbsp;&nbsp;<br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> ReadIni(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Section,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Key,</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> Default) <br>&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> GetPrivateProfileInt(Section,Key,Default,IniFileName); <br>&nbsp;&nbsp; } <br><br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> ReadIni(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Section,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Key,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Default) <br>&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuilder temp </span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">new</span><span style="COLOR: rgb(0,0,0)"> StringBuilder(</span><span style="COLOR: rgb(0,0,0)">1024</span><span style="COLOR: rgb(0,0,0)">);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> rec</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">GetPrivateProfileString(Section,Key,Default,temp,</span><span style="COLOR: rgb(0,0,0)">1024</span><span style="COLOR: rgb(0,0,0)">,IniFileName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)"> temp.ToString(); <br>&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> WriteIni(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Section,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Key,</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)"> intValue) <br>&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WritePrivateProfileString(Section,Key,intValue.ToString(),IniFileName); <br>&nbsp;&nbsp; } <br><br>&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">public</span><span style="COLOR: rgb(0,0,0)"> </span><span style="COLOR: rgb(0,0,255)">void</span><span style="COLOR: rgb(0,0,0)"> WriteIni(</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Section,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> Key,</span><span style="COLOR: rgb(0,0,255)">string</span><span style="COLOR: rgb(0,0,0)"> strValue) <br>&nbsp;&nbsp; {&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WritePrivateProfileString(Section,Key,strValue,IniFileName); <br>&nbsp;&nbsp; }<br>} <br>}</span></p>
<p>最好是加上判断文件是否存在，不存在则进行创建文件、错误处理等功能。</p><img src ="http://www.cppblog.com/limk/aggbug/57530.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/limk/" target="_blank">李明坤</a> 2008-07-30 17:10 <a href="http://www.cppblog.com/limk/archive/2008/07/30/57530.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#中调试C++的DLL</title><link>http://www.cppblog.com/limk/archive/2008/07/30/57529.html</link><dc:creator>李明坤</dc:creator><author>李明坤</author><pubDate>Wed, 30 Jul 2008 08:54:00 GMT</pubDate><guid>http://www.cppblog.com/limk/archive/2008/07/30/57529.html</guid><wfw:comment>http://www.cppblog.com/limk/comments/57529.html</wfw:comment><comments>http://www.cppblog.com/limk/archive/2008/07/30/57529.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/limk/comments/commentRss/57529.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/limk/services/trackbacks/57529.html</trackback:ping><description><![CDATA[<div class=item-content style="MARGIN-LEFT: 0px">被C#调用的DLL一般只需要把导出的函数以适当的形式呈现即可调用，比如<br>extern "C" __declspec(dllexport)<br>BOOL Integrate3 (){...}，这样的函数，在C#里面声明如：</div>
<div class=item-content style="MARGIN-LEFT: 0px">
<p>[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static extern bool Integrate3();，这里的调用相对是简单的，而有些数据类型则必须通过MarshalAs来做托管类型的转换，如：</p>
<p>extern "C" __declspec(dllexport)<br>BOOL Integrate (LPCWSTR file1, LPCWSTR file2, LPCWSTR outputFile){...}</p>
<p>由于数据类型不一致，所以在声明时要注意把类型转换过来。</p>
<p>[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static extern bool Integrate([In, MarshalAs(UnmanagedType.LPWStr)]string file1, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [In, MarshalAs(UnmanagedType.LPWStr)]string file2, [In, MarshalAs(UnmanagedType.LPWStr)]string outputFile);</p>
<p>这样调用基本是没有问题，重点在于数据类型的转换。多试过几次了就不问题了。</p>
<p>另外一个小小的实践经验就是在C#中调试C＋＋的DLL，知道了就是一句话，不知道就要搞半天，在C#项目属性中&#8220;启用调试项&#8221;中一项：&#8220;启用非托管代码调试&#8221;，钩上这个，就万事大吉了，就像你调试一般的程序一样。</p>
<p>C#调用C++的DLL时，参数传递便成了一个问题。今天我碰到的一个问题是，在C++中导出的函数的参数是string类型的，在C#中通过string的参数调用时，便会出现该内存已损坏或不能读取的异常信息。后来我把C++的导出函数的参数由string改为LPTSTR类型，也即char*类型，然后在C#中对应的参数改为StringBuilder类型，既解决了传进去的参数问题，又解决了传出参数的问题。</p>
</div>
<div class=item-content style="MARGIN-LEFT: 0px">DllImport知识拓展：DllImport&nbsp;</div>
<div class=item-content style="MARGIN-LEFT: 0px">&nbsp;.net 框架程序可以通过静态 DLL 入口点的方式来访问本机代码库。DllImport 属性用于指定包含外部方法的实现的dll 位置。</div>
<p class=item-content style="MARGIN-LEFT: 0px">DllImport 属性定义如下： <br>&nbsp;&nbsp; <br>namespace System.Runtime.InteropServices <br>{ <br>　[AttributeUsage(AttributeTargets.Method)] <br>　public class DllImportAttribute: System.Attribute <br>　{ <br>　　public DllImportAttribute(string dllName) {...} <br>　　public CallingConvention CallingConvention; <br>　　public CharSet CharSet; <br>　　public string EntryPoint; <br>　　public bool ExactSpelling; <br>　　public bool PreserveSig; <br>　　public bool SetLastError; <br>　　public string Value { get {...} } <br>　} <br>} <br>&nbsp;&nbsp; <br>　　说明： <br>&nbsp;&nbsp; <br>　1、DllImport只能放置在方法声明上。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;2、DllImport具有单个定位参数：指定包含被导入方法的 dll 名称的 dllName 参数。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;3、DllImport具有五个命名参数： <br>　　&nbsp;&nbsp; a、CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention，则使用默认值 CallingConvention.Winapi。 <br>&nbsp;&nbsp; 　　b、CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet，则使用默认值 CharSet.Auto。 <br>　　　c、EntryPoint 参数给出 dll 中入口点的名称。如果未指定 EntryPoint，则使用方法本身的名称。 <br>　　　d、ExactSpelling 参数指示 EntryPoint 是否必须与指示的入口点的拼写完全匹配。如果未指定 ExactSpelling，则使用默认值 false。 <br>　　　e、PreserveSig 参数指示方法的签名应当被保留还是被转换。当签名被转换时，它被转换为一个具有 HRESULT 返回值和该返回值的一个名为 retval 的附加输出参数的签名。如果未指定&nbsp;&nbsp;&nbsp; PreserveSig，则使用默认值 true。 <br>&nbsp;&nbsp; 　　 f、SetLastError 参数指示方法是否保留 Win32"上一错误"。如果未指定 SetLastError，则使用默认值 false。&nbsp; <br>　4、它是一次性属性类。 <br>　5、此外，用 DllImport 属性修饰的方法必须具有 extern 修饰符。 </p>
下面是 C# 调用 Win32 MessageBox 函数的示例： <br>&nbsp;&nbsp; <br>using System; <br>using System.Runtime.InteropServices; <br>class MainApp <br>{
<p>&nbsp;&nbsp;&nbsp;&nbsp; //通过DllImport引用user32.dll类。MessageBox来自于user32.dll类 <br>　[DllImport("user32.dll", EntryPoint="MessageBox")] <br>　public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType); <br>　public static void Main() <br>　{ <br>　　MessageBox( 0, "您好，这是 PInvoke！", ".net", 0 ); <br>　} <br>} <br>面向对象的编程语言几乎都用到了抽象类这一概念，抽象类为实现抽象事物提供了更大的灵活性。C#也不例外, C#通过覆盖虚接口的技术深化了抽象类的应用。欲了解这方面的知识，请看下一节-覆盖虚接口</p>
<p>这里讲述的是C#调用标准动态库的问题, 在我以前的文件中讲到过, C#调用Win32API, 原理是一样的. 这里我详细讲解用C写一个标准的动态库, 然后让C#调用. (本篇适合初学者, 中间没有任何冗余代码, 简洁明了)<br>软件环境: VC6.0(当然其他版本的VC5也可以)<br>1.制作标准动态库</p>
<p><br>__declspec(dllexport) int __cdecl add(int, int);//这一句是声明动态库输出一个可供外不调用的函数原型.<br>int add(int a,int b) {//实现这个函数<br>return a+b;<br>}</p>
<p><br>以上简单3行代码,声明一个add的方法, 输入参数是两个int参数,返回这两个数之和. 保存为MyLib.c<br>然后执行编译命令.<br>H:\XSchool\C#-School\HowTo&gt;cl /LD MyLib.c<br>Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86<br>Copyright (C) Microsoft Corp 1984-1998. All rights reserved.</p>
<p>MyLib.c<br>Microsoft (R) Incremental Linker Version 6.00.8447<br>Copyright (C) Microsoft Corp 1992-1998. All rights reserved.</p>
<p>/out:MyLib.dll<br>/dll<br>/implib:MyLib.lib<br>MyLib.obj<br>&nbsp;&nbsp; Creating library MyLib.lib and object MyLib.exp</p>
<p>确信有以上输出, 说明编译成功生成了动态库.</p>
<p>2.编写C-Sharp程序调用该动态库<br>using System;<br>using System.Runtime.InteropServices;//这是用到DllImport时候要引入的包</p>
<p>public class InvokeDll {<br>[DllImport("MyLib.dll", CharSet=CharSet.Auto)]<br>static extern int add(int a,int b);//声明外部的标准动态库, 跟Win32API是一样的.</p>
<p>public static void Main() {<br>Console.WriteLine(add(10,30));<br>}<br>}<br>保存为InvokeDll.cs文件, 与MyLib.dll置于同一目录, 编译该文件.<br>H:\XSchool\C#-School\HowTo&gt;csc invokedll.cs<br>将生成Invokedll.exe, 可以执行该文件.<br>以上是C-Sharp调用标准动态库的全过程, 本来觉得很简单的东西, 一直都没有想写, 碰巧今日遇一朋友问及此事, 就顺便写了下来.</p><img src ="http://www.cppblog.com/limk/aggbug/57529.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/limk/" target="_blank">李明坤</a> 2008-07-30 16:54 <a href="http://www.cppblog.com/limk/archive/2008/07/30/57529.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>va_list、va_start、va_arg、va_end宏的使用(转)</title><link>http://www.cppblog.com/limk/archive/2008/07/25/57116.html</link><dc:creator>李明坤</dc:creator><author>李明坤</author><pubDate>Fri, 25 Jul 2008 02:26:00 GMT</pubDate><guid>http://www.cppblog.com/limk/archive/2008/07/25/57116.html</guid><wfw:comment>http://www.cppblog.com/limk/comments/57116.html</wfw:comment><comments>http://www.cppblog.com/limk/archive/2008/07/25/57116.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/limk/comments/commentRss/57116.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/limk/services/trackbacks/57116.html</trackback:ping><description><![CDATA[<p><span>当你的函数的参数个数不确定时，就可以使用上述宏进行动态处理，这无疑为你的程序增加了灵活性。</span></p>
<p><span><font size=5>Example:</font></span></p>
<span>
<p class=MsoNormal style="BACKGROUND: #f1f1f1; MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">◎</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">用法1</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">:<br>func( Type para1, Type para2, Type para3, ... )<br>{<br>&nbsp;&nbsp;&nbsp; /****** Step 1 ******/<br>&nbsp;&nbsp;&nbsp; va_list ap;<br>&nbsp;&nbsp;&nbsp; va_start( ap, para3 ); //</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">一定要</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">&#8220;...&#8221;</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">之前的那个参数</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; /****** Step 2 ******/<br>&nbsp;&nbsp;&nbsp; //</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">此时</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">ap</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">指向第一个可变参数</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><br>&nbsp;&nbsp;&nbsp; //</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">调用</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">va_arg</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">取得里面的值</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt"><br>&nbsp;&nbsp;&nbsp; Type xx = va_arg( ap, Type ); <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //Type</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">一定要相同，如</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">:<br>&nbsp;&nbsp;&nbsp; //char *p = va_arg( ap, char *);<br>&nbsp;&nbsp;&nbsp; //int i = va_arg( ap, int );<o:p></o:p></span></p>
<p class=MsoNormal style="BACKGROUND: #f1f1f1; MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp; //</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">如果有多个参数继续调用</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">va_arg<o:p></o:p></span></p>
<p class=MsoNormal style="BACKGROUND: #f1f1f1; MARGIN: 0cm 0cm 0pt; WORD-BREAK: break-all; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">&nbsp;&nbsp;&nbsp; /****** Step 3 ******/<br>&nbsp;&nbsp;&nbsp; va_end(ap); //For robust!<br>}<o:p></o:p></span></p>
<p><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-font-kerning: 0pt">◎</span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: 宋体; mso-bidi-font-family: Tahoma; mso-font-kerning: 0pt; mso-ascii-font-family: Tahoma; mso-hansi-font-family: Tahoma">用法2</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: Tahoma; mso-font-kerning: 0pt">:</span></span></p>
<p><span>CString AppendString(CString str1,...)//一个连接字符串的函数，参数个数可以动态变化<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPCTSTR str=str1;//str需为指针类型，因为va_arg宏返回的是你的参数的指针，但是如果你的参数为int等简&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; CString res;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; va_list marker;&nbsp;&nbsp;&nbsp;&nbsp; //你的类型链表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; va_start(marker,str1);//初始化你的marker链表</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(str!="ListEnd")//ListEnd:参数的结束标志，十分重要，在实际中需自行指定<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res+=str;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str=va_arg(marker,CString);//取得下一个指针<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; va_end(marker);//结束，与va_start合用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return res;<br>}</span></p>
<p><span>int main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CString&nbsp;&nbsp;&nbsp; str=AppendString("xu","zhi","hong","ListEnd");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;str.GetBuffer(str.GetLength())&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}</span></p>
<p><span>输出</span><span> xuzhihong<br></span><span>CString </span><span>AppendString(CString str1,...)</span><span>，因为连接字符串的参数可以动态变化，你不知用户要进行连接的字符串个数是多少，所以你可以用</span><span>&#8230;</span><span>来代替。但是要注意的是你的函数要有一个参数作为标志来表示结束，否则会出错。在上例中用</span><span><font face=宋体>ListEnd</font></span><span>作为结束符。还有</span><span>va_arg</span><span>返回的是你参数内容的指针。上例在支持</span><span>MFC</span><span>程序的</span><span>console</span><span>下运行通过。</span></p>
<p><span><span class=a14c>可变参数函数的原型声明格式为：<br><br>type VAFunction(type arg1, type arg2, &#8230; );<br><br>参数可以分为两部分：个数确定的固定参数和个数可变的可选参数。函数至少需要一个固定参数，固定参数的声明和普通函数一样；可选参数由于个数不确定，声明时用"&#8230;"表示。固定参数和可选参数公同构成一个函数的参数列表。<br><br>借助上面这个简单的例2，来看看各个va_xxx的作用。<br><br>va_list arg_ptr：定义一个指向个数可变的参数列表指针；<br><br>va_start(arg_ptr, argN)：使参数列表指针arg_ptr指向函数参数列表中的第一个可选参数，说明：argN是位于第一个可选参数之前的固定参数，（或者说，最后一个 固定参数；&#8230;之前的一个参数），函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的。如果有一va函数的声明是void va_test(char a, char b, char c, &#8230;)，则它的固定参数依次是a,b,c，最后一个固定参数argN为c，因此就是va_start(arg_ptr, c)。<br><br>va_arg(arg_ptr, type)：返回参数列表中指针arg_ptr所指的参数，返回类型为type，并使指针arg_ptr指向参数列表中下一个参数。<br><br>va_copy(dest, src)：dest，src的类型都是va_list，va_copy()用于复制参数列表指针，将dest初始化为src。<br><br>va_end(arg_ptr)：清空参数列表，并置参数指针arg_ptr无效。说明：指针arg_ptr被置无效后，可以通过调用va_start ()、va_copy()恢复arg_ptr。每次调用va_start() / va_copy()后，必须得有相应的va_end()与之匹配。参数指针可以在参数列表中随意地来回移动，但必须在va_start() &#8230; va_end()之内。<br><br></span><ccid_nobr></ccid_nobr>va函数的实现就是对参数指针的使用和控制。<br><br>
<table cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td>
            <pre><code><br>typedef char *&nbsp;&nbsp; va_list;&nbsp;&nbsp; // x86平台下va_list的定义<br></code></pre>
            </td>
        </tr>
    </tbody>
</table>
<br><br>函数的固定参数部分，可以直接从函数定义时的参数名获得；对于可选参数部分，先将指针指向第一个可选参数，然后依次后移指针，根据与结束标志的比较来判断是否已经获得全部参数。因此，va函数中结束标志必须事先约定好，否则，指针会指向无效的内存地址，导致出错。<br><br>这里，移动指针使其指向下一个参数，那么移动指针时的偏移量是多少呢，没有具体答案，因为这里涉及到内存对齐（alignment）问题，内存对齐跟具体 使用的硬件平台有密切关系，比如大家熟知的32位x86平台规定所有的变量地址必须是4的倍数(sizeof(int) = 4)。va机制中用宏_INTSIZEOF(n)来解决这个问题，没有这些宏，va的可移植性无从谈起。<br><br>首先介绍宏_INTSIZEOF(n)，它求出变量占用内存空间的大小，是va的实现的基础。<br><br>
<table cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td>
            <pre><code><br>#define _INTSIZEOF(n)&nbsp;&nbsp; ((sizeof(n)+sizeof(int)-1)&amp;~(sizeof(int) - 1) ) <br></code></pre>
            </td>
        </tr>
    </tbody>
</table>
<br><br>
<table cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td>
            <pre><code><br>#define va_start(ap,v) ( ap = (va_list)&amp;v + _INTSIZEOF(v) )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第一个可选参数地址<br>#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址<br>#define va_end(ap)&nbsp;&nbsp;&nbsp; ( ap = (va_list)0 )&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></code></pre>
            </td>
        </tr>
    </tbody>
</table>
<br><br>下表是针对函数int TestFunc(int n1, int n2, int n3, &#8230;)<br><br>参数传递时的内存堆栈情况。（C编译器默认的参数传递方式是__cdecl。）<br><br>对该函数的调用为int result = TestFunc(a, b, c, d. e); 其中e为结束标志。<br><br></span></p>
<center><img alt="" src="http://tech.ccidnet.com/pub/attachment/2005/4/418433.gif"><br></center>
<p>从上图中可以很清楚地看出va_xxx宏如此编写的原因。<br><br>1． va_start。为了得到第一个可选参数的地址，我们有三种办法可以做到：<br><br>A) = &amp;n3 + _INTSIZEOF(n3)<br><br>// 最后一个固定参数的地址 + 该参数占用内存的大小<br><br>B) = &amp;n2 + _INTSIZEOF(n3) + _INTSIZEOF(n2)<br><br>// 中间某个固定参数的地址 + 该参数之后所有固定参数占用的内存大小之和<br><br>C) = &amp;n1 + _INTSIZEOF(n3) + _INTSIZEOF(n2) + _INTSIZEOF(n1)<br><br>// 第一个固定参数的地址 + 所有固定参数占用的内存大小之和<br><br>从编译器实现角度来看，方法B)，方法C)为了求出地址，编译器还需知道有多少个固定参数，以及它们的大小，没有把问题分解到最简单，所以不是很聪明的途 径，不予采纳；相对来说，方法A)中运算的两个值则完全可以确定。va_start()正是采用A)方法，接受最后一个固定参数。调用va_start ()的结果总是使指针指向下一个参数的地址，并把它作为第一个可选参数。在含多个固定参数的函数中，调用va_start()时，如果不是用最后一个固定 参数，对于编译器来说，可选参数的个数已经增加，将给程序带来一些意想不到的错误。(当然如果你认为自己对指针已经知根知底，游刃有余，那么，怎么用就随 你，你甚至可以用它完成一些很优秀（高效）的代码，但是，这样会大大降低代码的可读性。)<br><br>注意：宏va_start是对参数的地址进行操作的，要求参数地址必须是有效的。一些地址无效的类型不能当作固定参数类型。比如：寄存器类型，它的地址不是有效的内存地址值；数组和函数也不允许，他们的长度是个问题。因此，这些类型时不能作为va函数的参数的。<br><br>2． va_arg身兼二职：返回当前参数，并使参数指针指向下一个参数。<br><br>初看va_arg宏定义很别扭，如果把它拆成两个语句，可以很清楚地看出它完成的两个职责。<br><br>
<table cellSpacing=0 cellPadding=5 width="100%" bgColor=#cccccc border=1>
    <tbody>
        <tr>
            <td>
            <pre><code><br>#define va_arg(ap,t)&nbsp;&nbsp;&nbsp; ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一个参数地址<br>// 将( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )拆成：<br>/* 指针ap指向下一个参数的地址 */<br>1． ap += _INTSIZEOF(t)；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 当前，ap已经指向下一个参数了<br>/* ap减去当前参数的大小得到当前参数的地址，再强制类型转换后返回它的值 */<br>2． return *(t *)( ap - _INTSIZEOF(t)) <br></code></pre>
            </td>
        </tr>
    </tbody>
</table>
<br><br>回想到printf/scanf系列函数的%d %s之类的格式化指令，我们不难理解这些它们的用途了- 明示参数强制转换的类型。<br><br>(注：printf/scanf没有使用va_xxx来实现，但原理是一致的。)<br><br>3．va_end很简单，仅仅是把指针作废而已。<br><br>#define va_end(ap) (ap = (va_list)0) // x86平台<br><br><strong>四、 简洁、灵活，也有危险</strong><br><br>从va的实现可以看出，指针的合理运用，把C语言简洁、灵活的特性表现得淋漓尽致，叫人不得不佩服C的强大和高效。不可否认的是，给编程人员太多自由空间必然使程序的安全性降低。va中，为了得到所有传递给函数的参数，需要用va_arg依次遍历。其中存在两个隐患：<br><br>1）如何确定参数的类型。<br><br>va_arg在类型检查方面与其说非常灵活，不如说是很不负责，因为是强制类型转换，va_arg都把当前指针所指向的内容强制转换到指定类型；<br><br>2）结束标志。如果没有结束标志的判断，va将按默认类型依次返回内存中的内容，直到访问到非法内存而出错退出。例2中SqSum()求的是自然数的平方 和，所以我把负数和0作为它的结束标志。例如scanf把接收到的回车符作为结束标志，大家熟知的printf()对字符串的处理用'\0'作为结束标 志，无法想象C中的字符串如果没有'\0'， 代码将会是怎样一番情景，估计那时最流行的可能是字符数组，或者是malloc/free。<br><br>允许对内存的随意访问，会留给不怀好意者留下攻击的可能。当处理cracker精心设计好的一串字符串后，程序将跳转到一些恶意代码区域执行，以使cracker达到其攻击目的。(常见的exploit攻击)所以，必需禁止对内存的随意访问和严格控制内存访问边界。<br></p><img src ="http://www.cppblog.com/limk/aggbug/57116.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/limk/" target="_blank">李明坤</a> 2008-07-25 10:26 <a href="http://www.cppblog.com/limk/archive/2008/07/25/57116.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>