??xml version="1.0" encoding="utf-8" standalone="yes"?> log4cpp是个ZLGPL的开源项目,是基于优U的日志处理跟t项目Java语言的log4jULq来的。log4j介绍的文很多,在java领域使用的也比较q泛Q而这个功能强大的库对国内的C++语言开发h员却使用的不多。这里从开发h员用的角度介绍q个库,使开发h员用最的代h快掌握q种技术。下面先单介l一下这个项目的优点Q也是log4j的优点)Q然后分原理Q手动用步骤,配置文g驱动方式使用步骤Q其他考虑{方面进行讨论。以下讨论基于log4cpp0.3.4b?/p>
log4cpp?个主要的lgQcategoriesQ类别)、appendersQ附加目的地Q、和 layoutsQ布局Q。(Z方便大家理解Q文中尽量用英文原词) layoutcL制输出日志消息的昄样式Q看h像什么)。log4cpp当前提供以下layout格式Q?/p>
appendercȝ来输出日志(被layout格式化后的)C些设备上。比如文件、syslog服务、某个socket{。可以定义自q appenderc输出日志信息到别的讑֤上,比如应用自n的日子处理进E、数据库{。appender和layout的关pLlayout附在 appender上,appenderc调用layout处理完日志消息后Q记录到某个讑֤上。log4cpp当前提供以下appenderQ?/p>
category cȝ正完成记录日志功能,两个主要l成部分是appenders和priorityQ优先Q。优先控制哪类日志信息可以被这个category记录Q当前优先分ؓQNOTSET, DEBUG, INFO, NOTICE, WARN, ERROR, CRIT, ALERT ?FATAL/EMERG 。每个日志信息有个优先Q每个category有个优先U,当消息的优先U大于等于category的优先Ӟq个消息才会被category记录Q否则被忽略。优先的关pd下。categorycdappender的关pLQ多个appender附在category上,q样一个日志消息可以同时输出到多个讑֤上?/p>
NOTSET < DEBUG < INFO < NOTICE < WARN < ERROR < CRIT < ALERT < FATAL = EMERG category被组l成一个树Q子category创徏时优先~省NOTSETQcategory~省会承父category?appender。而如果不希望q种appender的承关p,log4cpp允许使用additivity 标签Qؓfalse时新的appender取代category的appender列表?/p>
Z更好的理解上面的概念下面以手动用方式D例?/p>
手动使用log4cpp的基本步骤如下: 另一个非怼U的特征就是通过d配置文gQ确定category、appender、layout{对象。也是我们非常推荐的使用方式Q可以灵zd通过配置文g定义所有地对象及其属性,不用重新~码Q动态更Ҏ志记录的{略?/p>
Log4cpp主要提供?log4cpp::PropertyConfigurator 和log4cpp::SimpleConfigurator两种机制Q文件格式)Q但 log4cpp::SimpleConfigurator来不再支持了,而且格式非常单,q里׃多说明,自己看源码吧?/p>
配置文g的格式和log4j的配|文件一P是标准的java属性文件格式。下面是附带的例子配|文Ӟ 配置文g语法如下Q不是很规范Q结合上面的例子Q应该可以看懂?/p>
基本使用步骤是: 下面是个单的使用代码Q用v来是非常方便的: 性能问题Q可能是很多想用log4cpp的程序员兛_的问题。在参考资?中有一D|q。结论就是log4j以及log4cpp是以性能为首要目标的Q如果关闭日志记录的话,Ҏ能影响可以忽略Q打开日志记录Q主要消耗是在记录动作,而不是库的管理过E;所以你可攑ֿ的用。实在要q性能的话。可以从下面斚w提高Q?/p>
输出的日志消息不要用复杂的转换或者处理,比如Q?sub1.debug(string("Current num is") + i + GetCurStat()); q种情况即不进行日志处理,括号中的语句q是会执行。变通方法是Q?/p>
安全性问题对于商业Y件开发可能也是问题。可能不希望别h通过修改配置文g获取E序的调试等E序内部q行情况的日志信息。比较稳妥的Ҏ或者是加密配置文gQ运行中解密Q输出到临时文g后读取;或者在发行版本里读取配|文件后Q强行把低于某个优先U的category讑ֈ比较高的优先U?/p>
多线E安全性问题。当前log4cppq没有宣U自己是多线E安全的Q不q其代码中大多数可能冲突的地斚w增加了线E互斥控Ӟ对多U程环境应该问题不大。但Z加入q个Ҏ,linux下编译log4cppӞconfigure请加?-with-pthreads 或?-with-omnithreads选项。Win版本已经加入对MSU程的支持?/p>
1. Logging and Tracing in C++ Simplified: Traveling the Road Last Traveled by a Previously Invented Wheel 2. log4j 提供了对日志记录的控?br/>http://www-900.ibm.com/developerWorks/cn/java/jw-log4j/index.shtml 3. 使用Log4jq行日志操作 4. log4cpp主页 5. log4j主页 6. log4cplus主页 7. log4c主页 李群Q关注于|络安全产品的开发、研IӞ软g开发过E等斚w。您可以通过liqun@nsfocus.com和他联系?/p>
l盟U技
2003 q?9 ?
可以动态控制日志记录别,在效率和功能中进行调_
所有配|可以通过配置文gq行动态调_
多语a支持Q包括JavaQlog4jQ,C++Qlog4cpp、log4cplusQ,CQlog4cQ,pythonQlog4pQ等Q?br/>...
log4cpp::BasicLayout // ?旉?优先U(priorityQ下文介l)
// cdQcategoryQ下文介l)
// NDC标签Qnested diagnostic contexts 下文介绍Q? 日志信息"? // 如:1056638652 INFO main : This is some info
log4cpp::PatternLayout // 让用h据类g C 语言 printf 函数的{换模式来指定输出格式。格式定义见代码附带文?log4cpp::SimpleLayout // ?优先U(priorityQ?- 日志信息"格式昄?
log4cpp::IdsaAppender // 发送到IDS或者logger, 详细?http://jade.cs.uct.ac.za/idsa/
log4cpp::FileAppender // 输出到文?log4cpp::RollingFileAppender // 输出到回hӞ卛_文g到达某个大小后回?log4cpp::OstreamAppender // 输出C个ostreamc?log4cpp::RemoteSyslogAppender // 输出到远Esyslog服务?log4cpp::StringQueueAppender // 内存队列
log4cpp::SyslogAppender // 本地syslog
log4cpp::Win32DebugAppender // 发送到~省pȝ调试?log4cpp::NTEventLogAppender // 发送到win 事g日志
// FileName: test_log4cpp1.cpp
// Test log4cpp by manual operation.
// Announce: use as your own risk.
// Compile : g++ -otest1 -llog4cpp test_log4cpp1.cpp
// Run : ./test1
// Tested : RedHat 7.2 log4cpp0.3.4b
// Author : liqun (liqun@nsfocus.com)
// Data : 2003-6-27
#include "log4cpp/Category.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/BasicLayout.hh"
int main(int argc, char* argv[])
{
// 1实例化一个layout 对象
log4cpp::Layout* layout =
new log4cpp::BasicLayout();
// 2. 初始化一个appender 对象
log4cpp::Appender* appender = new
log4cpp::FileAppender("FileAppender",
"./test_log4cpp1.log");
// 3. 把layout对象附着在appender对象? appender->setLayout(layout);
// 4. 实例化一个category对象
log4cpp::Category& warn_log =
log4cpp::Category::getInstance("mywarn");
// 5. 讄additivity为falseQ替换已有的appender
warn_log.setAdditivity(false);
// 5. 把appender对象附到category? warn_log.setAppender(appender);
// 6. 讄category的优先Q低于此优先U的日志不被记录
warn_log.setPriority(log4cpp::Priority::WARN);
// 记录一些日? warn_log.info("Program info which cannot be wirten");
warn_log.debug("This debug message will fail to write");
warn_log.alert("Alert info");
// 其他记录日志方式
warn_log.log(log4cpp::Priority::WARN, "This will be a logged warning");
log4cpp::Priority::PriorityLevel priority;
bool this_is_critical = true;
if(this_is_critical)
priority = log4cpp::Priority::CRIT;
else
priority = log4cpp::Priority::DEBUG;
warn_log.log(priority,"Importance depends on context");
warn_log.critStream() << "This will show up << as "
<< 1 << " critical message"
<< log4cpp::CategoryStream::ENDLINE;
// clean up and flush all appenders
log4cpp::Category::shutdown();
return 0;
}
# a simple test config
#定义?个category sub1, sub2, sub1.sub2
log4j.rootCategory=DEBUG, rootAppender
log4j.category.sub1=,A1
log4j.category.sub2=INFO
log4j.category.sub1.sub2=ERROR, A2
# 讄sub1.sub2 的additivity属?log4j.additivity.sub1.sub2=false
#定义rootAppendercd和layout属?log4j.appender.rootAppender=org.apache.log4j.ConsoleAppender
log4j.appender.rootAppender.layout=org.apache.log4j.BasicLayout
#定义A1的属?log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.fileName=A1.log
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout
#定义A2的属?log4j.appender.A2=org.apache.log4j.ConsoleAppender
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=The message '%m' at time %d%n
log4j / log4cpp . [category / appender].[category or appender 's name].[category or appender 's property]
= [Appender / Layout / property's value / Priority, appender name1 [appender name2 ...]]
[appender]
{ConsoleAppender}
{FileAppender} // 当appender的类型是FileAppenderӞ可以定义它下面的属性? [fileName] string foobar // 格式是:属性名 值的cd ~省? [append] bool true
{RollingFileAppender}
[fileName] string foobar
[maxFileSize] num 10*1024*1024
[maxBackupIndex] num 1
[append] bool true
{SyslogAppender}
[syslogName] string syslog
[syslogHost] string localhost
[facility] num -1 // * 8 to get LOG_KERN, etc. compatible values.
[portNumber] num -1
{IdsaAppender}
[idsaName] string foobar
{Win32DebugAppender}
{NTEventLogAppender}
[source] string foobar
[threshold] string "" // 全部
// 如果此类型appender需要layoutQ必d义此appender的下面属? [layout]
{BasicLayout}
{SimpleLayout}
{PatternLayout} // 当layout的值是BasicLayoutӞ需要定义下面的属性? [ConversionPattern]
[rootCategory]
[additivity]
[category name] bool true
// FileName: test_log4cpp2.cpp
// Test log4cpp by config file.
// Announce: use as your own risk.
// Compile : g++ -llog4cpp test_log4cpp2.cpp
// Run : ./a.out
// Tested : RedHat 7.2 log4cpp0.3.4b
// Author : liqun (liqun@nsfocus.com)
// Data : 2003-6-27
#include "log4cpp/Category.hh"
#include "log4cpp/PropertyConfigurator.hh"
int main(int argc, char* argv[])
{
// 1 d解析配置文g
// d出错, 完全可以忽略Q可以定义一个缺省策略或者用系l缺省策? // BasicLayout输出所有优先日志到ConsoleAppender
try {
log4cpp::PropertyConfigurator::configure("./log4cpp.conf");
} catch(log4cpp::ConfigureFailure& f) {
std::cout << "Configure Problem " << f.what() << std::endl;
return -1;
}
// 2 实例化category对象
// q些对象即配置文g没有定义也可以用,不过其属性承其父category
// 通常使用引用可能不太方便Q可以用指针,以后做指针? // log4cpp::Category* root = &log4cpp::Category::getRoot();
log4cpp::Category& root = log4cpp::Category::getRoot();
log4cpp::Category& sub1 =
log4cpp::Category::getInstance(std::string("sub1"));
log4cpp::Category& sub3 =
log4cpp::Category::getInstance(std::string("sub1.sub2"));
// 3 正常使用q些category对象q行日志处理? // sub1 has appender A1 and rootappender.
sub1.info("This is some info");
sub1.alert("A warning");
// sub3 only have A2 appender.
sub3.debug("This debug message will fail to write");
sub3.alert("All hands abandon ship");
sub3.critStream() << "This will show up << as " << 1 << " critical message"
<< log4cpp::CategoryStream::ENDLINE;
sub3 << log4cpp::Priority::ERROR
<< "And this will be an error"
<< log4cpp::CategoryStream::ENDLINE;
sub3.log(log4cpp::Priority::WARN, "This will be a logged warning");
return 0;
}
if(sub1.isDebugEnabled())
{
sub1.debug(string("Current num is") + i + GetCurStat());
}
http://soldc.sun.com/articles/logging.html
http://www-900.ibm.com/developerWorks/cn/java/l-log4j/index.shtml
http://sourceforge.net/projects/log4cpp/
http://jakarta.apache.org/log4j/docs/index.html
http://log4cplus.sourceforge.net/
http://log4c.sourceforge.net/
]]>
一个空cȝ译器自动l其d的函数有哪几?
class Empty
{
public:
Empty(); // ~省构造函?br/>Empty( const Empty& ); // 拯构造函?br/>~Empty(); // 析构函数
Empty& operator=( const Empty& ); // 赋D符
Empty* operator&(); // 取址q算W?br/>const Empty* operator&() const; // 取址q算W?const
};
在网上找到的解决ҎQ?a >http://www.codeguru.com/cpp/w-p/dll/importexportissues/article.php/c123/
DOS时代c语言开发的l典工具Q目前适合两类Z用:c语言beginnerQ尤其是学生一族)Q具有怀旧情节的专业人士Q)
----QVisual C++ 6.0/7.0
E_而强大的IDE开发环境,h丰富的调试功能,定制宏的功能也是其一大特艌ӀMicrosoft的经怹作,功能强大自不必言说。附带的一些工具也很不错,比如QSpy++。但~译器较之同c,支持c++标准的程度不够好Q尤?.0及以前的版本?/p>
----QBCB
Borland的C++ Builder是可以与VCҎ的另一个功能强大的IDEQ速度和稳定性稍逊,但对c++标准支持的程度较好?/p>
----QCygwin
Windowsq_下的C++~译器,ZgccQ又完全兼容WindowҎ的东西,比如对winsock的支持。从http://www.cygwin.com可以扑ֈ有关Cygwin的详l信息?/p>
----QDev-c++
Windowsq_下,一个类似VC、BCB的c++ IDE开发环境,属于׃n软g。界面亲切优雅,size也不大,?.9.x版有中文语言支持Q无需汉化。编译器ZgccQ完全支持STL。但是对于规模较大的软g目Q恐怕难以胜仅R可以从:http://www.bloodshed.net/dev/devcpp.html扑ֈ有关Dev-c++的有关信息?/p>
----QSource Insight
有着和Dev c++一h亮的界面Q提供代码的~辑和察看功能,h丰富的语法加亮功能,可以像VC一栯动弹出成员函数的提示Qƈh快速方便的函数跌{功能Q但是蟩转速度g有点慢)。只是默认设|不适合Ӟ需要仔l的调整和修攏V无法查扄typedef之后的名字?/p>
辅助工具
----QVisual Assist
VC IDE环境下的辅助~程工具Q能识别各种关键字、函数、成员变量,自动l出tipQƈ自动更正大小写错误,标示拼写错误{。是VC开发的良好伴G?/p>
----QUnderstand for C++
一ƾc/c++IDE~程的辅助工P支持反向工程Q代码导向和一些统计功能,?span style="COLOR: #4c408c">http://www.scitools.com可以扑ֈ有关Understand for C++的详l信息?/p>
E序~辑?/strong>
----QEditPlus
一Ƒ־不错的文本编辑YӞ功能强大却又十分dy。支持不同语a的语法加亮,q有Projectl织功能Q具有丰富的自定义功能。通过讄User ToolQ可以和其他语言~译器结合,形成一个简单的IDE?/p>
----QUltra Edit
功能和EditPlus相当Q通过脚本文g提供的配|功能可以定制编辑环境,但自6.0版以后一直没多大变化Q就~程而言Q自定义讄没有EditPlus方便?/p>
----QEMACS
公认的世界上功能最多,最复杂的文本编辑器Q其实也可以当作E序员用的编辑器?/p>
----QVisual Slick Edit
一个功能强大的E序员用~辑器。最值得一提的是其定制功能Q很好用Q可以和EMACS相比。自带了一套PCODE解释器,用c的语法,q可以挂接动态库。配合mingw一起用很方便。从http://www.slickedit.com可以扑ֈ有关SlickEdit的详l信息?/p>
----QIQEdit
全功能的E序员用~辑器,界面很漂亮,?span style="COLOR: #4c408c">http://pwksoftware.com可以扑ֈ有关IQEdit的详l信息?/p>
UML/建模
----QRational Rose
强大的徏模工P早已"家喻h"Q功q自然不必多加评说了。从http://www.rationalsoftware.com.cn可以扑ֈ有关Rational Rose的详l信息?/p>
----QVisual Modeler
MS Visual Studio 6.0所附的工兗属于Rational和MicroSoft合作的战?a href="javascript:;" target="_self" onclick="javascript:tagshow(event, '%B2%FA%C6%B7');">产品Q是Rose的简化版?br/>----QVisio
Microsoft的徏模工P感觉更h性化一些,但功能没有Rose多、强、专Q支持正向的代码生成Q以及对代码的反向工E?/p>
----QTogether
另一Ƒ֊能强大的建模工具Q用java~写而成Q口不错,不过速度E稍慢了一些。从http://www.togethersoft.com可以扑ֈ有关Togather的详l信息,另外Q以下网址提供了一个有关Together的教E: http://www.cc.puv.fi/~tka/kurssit/Tietojarjestelmien_suunnittelu
/together/TCCGuide6
----QVisual UML
支持多种语言cdQ比如:VC、VB、DELPHI、CORBA IDL{,可以直接从UML设计囄成代码,单易用,完全适合Personal useQ界面也很清爽。从http://www.visualObject.com可以扑ֈ有关Visual UML的详l信息?/p>
----QSmartDraw
通用图表制作软gQ可以用来制作组l机构图、流E图、统计图表等。随带有囑ֺQ基本满_作各cd表的需要。从http://www.smartdraw.com可以扑ֈ有关SmartDraw的详l信息?/p>
----QPlayCase
国面向对象的徏模YӞ兼容UML和IDEFQ轻量软gQ只是界面看h有点_乃是高展先生用Delphi完成的?/p>
版本控制
----QClearCase
Rational的版本控制管理YӞ功能强大Q可以控制多U类型的文Q甚臛_括Word、Excel、PowerPoint文档。但使用复杂Q不易上手,且不是免费Y件?/p>
----QCVS
为基于Web的分布式协同开发提供了版本控制理手段Q且是免费YӞ可以通过脚本定制功能。但在权限控制方面功能相对较弱?/p>
----QVSS
微Y的版本控制管理工P功能相对单,适合于小型团队开发,其整合到微软的其他开发工具中Q用v来十分方ѝ?/p>
----QSourceOffSite
微Y为开发h员提供的q程讉KVSS数据库的工具Q数据库得以远E更斎ͼ以支持远E办公。其他的版本理工具q包括:PVCS、VCS、RCS{?/p>
XML
----Qexpat
用于d和处理XML文档的c函数库,最初是James Clark的个Z品,单轻巧,且速度快。但支持的编码方式有限,最遗憾的是不支持中文。从http://expat.sourceforge.net可以扑ֈ有关expat的详l信息?/p>
----Qxml4c
IBM的XML ParserQ用c++语言写就Q功能超U强大。号U支持多?00U字W编码,能够支持中文Q适合于大规模的xml应用。若只是很小范围的应用,则非最佳选择Q毕竟,你需?背负"U?2M左右的dll的沉重负担。从http://www.alphaworks.ibm.com/tech/xml4c可以扑ֈ有关xml4c的详l信息?/p>
----QXerces c++
Apache的XML目Q同hc++实现Q来源于IBM的xml4cQ因此编E接口也是和xml4c一致的。但是目前只支持数的字W编码,如ASCIIQUTF-8QUTF-16{,不能处理包含中文字符的XML文。从http://xml.apache.org/xerces-c可以扑ֈ有关Xerces c++的详l信息?/p>
试
----QCppUnit
一个c++的单元测试框Ӟ可以通过z试cȝ方式Q定制具体的试Ҏ。xUnit家族的一员,从JUnitUL而来QJUnit是Java语言的单元测试框架。从http://cppuint.sourceforge.net可以扑ֈ有关CppUint的详l信息?/p>
----QRational ROBOT
Rational的自动化试工具Q通过~写脚本的方式提供自动化试Ҏ。其GUI方式的脚本录制功能,有助于对GUI软gq行功能试Q其VU方式的脚本录制功能,有助于测试某些Y件的数据通讯功能?/p>
----QRational Purify
同样是Rational的自动化试工具Q不需要被程序的源代码,可以用来查内存访问错误、Windows API调用错误{,以完成Y件的可靠性测试,属于白盒试?/p>
其他的Rational试工具q包括:TestFactory、PureCoverage、TestManager{?/p>
日志
----Qlog4cpp
一个用于日志记录的c++函数库,可以内容以定制的方式记录到不同的目的地Q比如:文g、控制台syslog{,同时q可以通过控制记录U别来屏蔽掉某些无关记录。从http://log4cpp.sourceforge.net可以扑ֈ有关log4cpp的详l信息?/p>
注释
----QDoc++
注释文生成工具Q根据源E序中的文注释Q可以输出TeX和HTML格式的文。除了支持c/c++语言外,q支持IDL和java。仅提供命o行用方式。从http://docpp.sourceforge.net可以扑ֈ有关Doc++的详l信息?/p>
----QDoxygen
注释文档生成工具Q较之Doc++功能更ؓ齐全Q可以生成包括HTML、PDF、RTF在内的多U格式的文档Qƈ有GUI界面Q除了支持c/c++语言外,q支持IDL、java、PHP、c#{。从http://www.stack.nl/~dimitri/doxygen可以扑ֈ有关Doxygen的详l信息?/p>
我在学习VC,或者在阅读别h写的文章的时?偶尔到下面很多有趣?q且很奇怪的语句,整理h,以备后忘. 其实有些是不大容易想到的技巧,贴出来权当大伙饭后没事的品文,当然不要q多的看重类似的语句学习Q而忽略了基础知识?br/>
一. 奇怪的宏定?br/>(1) #define for if(0); else for
按照c++标准,for中定义的变量的作用域应该只在for循环中有?而VC却不?比如q样定义是不对的
for(int i=0;i<90;i++)
{
...;
}
for(int i=0;i<90;i++) //重复定义i变量
{
...;
}
如果加上标题的那?那么可以了,是让i作用域局限在else? q个问题在net中已l得到解冟?/p>
二、宏定义怪圈
#define wait_event(wq,condition) \
do{ \
if(condition) \
break; \
__wait_event(wq,condition); \
}while(0)
明明q句话只执行一?Z么还q用do-while语句?
假设有这样一个宏定义
#define macro(condition) \
if(condition) dosomething();
现在在程序中q样使用q个宏:
if(temp)
macro(i);
else
doanotherthing();
一切看h很正常,但是仔细x。这个宏会展开成:
if(temp)
if(condition) dosomething();
else
doanotherthing();
q时的else不是与第一个if语句匚wQ而是错误的与W二个if语句q行了匹配,~译通过了,但是q行的结果一定是错误的。ؓ了避免这个错误,我们使用do{?}while(0) 把它包裹hQ成Z个独立的语法单元Q从而不会与上下文发生淆。同时因为绝大多数的~译器都能够识别do{…}while(0)q种无用的@环ƈq行优化Q所以用这U方法也不会DE序的性能降低?br/>q个用法在linux源码中很常见?/p>
三、功能强大的解释
除了/* */?//解释以外Q你见过q样的解释方法了吗?
#if(0)
........
#endif
q样是ؓ了解释掉某段E序,而不影响其中?*...*/的作?便于调试Q?*.....*/是不能嵌套的,~译会出?
四、数l变?a[i]和i[a]
在程序里本应该用a[i]Q但i[a]竟然和a[i]输出的结果一栗ؓ什么。今天把问题整理如下Q?br/>i[a]是标准语法?[]"UCؓ下标q算W,其语法ؓQ?br/>postfix_expression [ expression ]
其中"postfix_expression"?expression"之中必须有一个是指针cdQ或数组Q,而另一个是整型?br/>例如下面的程序是完全合法的:
int a[]={0,1,2,3,4};
printf("%d\n",3[a]);
下标q算W参与的表达式在求解时仅仅是做一个变换而已Q将"postfix_expression [ expression ]"
改写? * ( postfix_expression + expression ) "Q因此a[3]?[a]分别改写?(a+3)?(3+a)Q?br/>可见二者是完全{h的。但注意不要用i[a]q种形式Q因为它不符合日怹惯?br/>实验代码Q?br/>#include "stdafx.h"
#include "iostream.h"
int f();
int main(int argc, char* argv[])
{
int a[20]={1,2,3,4,5,6,7,8,9};
cout<<a[f()]<<endl;
cout<<f()[a]<<endl;
return 0;
}
int f()
{
return 4;
}
实验l果Q?br/>4
4
Press any key to continue
五、双胞胎定义和声明:int x;x;
q儿是个关于宏的问题Q我曄qATL的串转换宏,包括W2AQ开始有些东西我q不太明白。ؓ了用这些宏Q必d函数的开始处用USES_CONVERSION来初始化某些局部变量。用q吧,但是看看q个宏的定义Q它有类g面的代码Q?/p>
// 在atlconv.h文g?br/>#define USES_CONVERSION \
int _convert; _convert; \
UINT _acp = GetACP(); _acp; \
LPCWSTR _lpw; _lpw; \
LPCSTR _lpa; _lpa
Z么它们用"int x;x;"--q种后面跟着变量的声明?
很多人都到q这个o人困惑的问题Q后来发现简单的{案是:止~译器的警告信息QwarningQ。如果单独有一行代码:
int x;
且从来没有用过xQ那么编译器汇报?unreferenced local variableQx",意思是未引用过的局部变量xQ如果将警告信息的输?br/>调到最大。ؓ了避免讨厌的警告QUSES_CONVERSION引用声明的变量?/p>
int x; // 声明
x; // 使用q个变量
在C++之前的时代,E序员有时在C中用函数形参做同L事情来避?unreferenced formal parameter"或其它的深奥费解的编译错误?/p>
void MyFunc(int x, char y)
{
x;
y;
?br/>}
当然Q现在用下面的代码可以更有效地完成同L事情Q?/p>
// 参数 x 不是?br/>void MyFunc(int /* x */)
{
?br/>}