??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人香蕉久久久久,久久最新精品国产,久久精品水蜜桃av综合天堂
http://www.shnenglu.com/ownwaterloo/zh-cn Tue, 06 May 2025 20:16:15 GMT Tue, 06 May 2025 20:16:15 GMT 60 C与C++的细微区别——省略Ş式参数名 http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_parameter_name.htmlOwnWaterloo OwnWaterloo Sun, 26 Apr 2009 07:01:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_parameter_name.html http://www.shnenglu.com/ownwaterloo/comments/81117.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_parameter_name.html#Feedback 5 http://www.shnenglu.com/ownwaterloo/comments/commentRss/81117.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/81117.html 在函数声明中Q?br>无论是Cq是在C++Q都可以省略 形式参数名?br>但是Q通常?strong>?/span>省略形式参数名?br> 在函数定义中Q?br>1. 当需要用Ş式参数的时候,昄Q必ȝ形式参数命名?br> 2. 当不需要用Ş式参数的时候,C与C++有微差异: —?C不能省略形式参数?/strong>Q?即 不用?br>—?C++可以省略形式参数?/strong>Q?strong style="COLOR: red">如果 不用?br>—?q且在C++中,如果l不使用的Ş式参数命名,可能会得C?strong>警告 ?br>
二、示例:
#include < stdio.h > void greeting_omit( const char * name); void greeting_unuse( const char * name); void greeting_nowarning( const char * name); int main( void ) { greeting_omit( "" ); greeting_unuse( "" ); greeting_nowarning( "" ); ( void )getchar(); return 0 ; }
三、三个函数分别实现如下: 三?
void greeting_omit( const char * ) { printf( " hello world\n " ); }
——在C中是错误Q?br>1. msvc : error C2055: expected formal parameter list, not a type list error C2055: 应输入Ş参表Q而不是类型表 2. gcc : Q报错更清晰一些) error: parameter name omitted 错误Q?省略参数?br> ——在C++中正,且无警告?br> 三?
void greeting_unuse( const char * name) { printf( " hello Cherrie\n " ); }
在C和C++中都正确Q但可能得到一个警告: 1. msvc : warning C4100: 'name' : unreferenced formal parameter warning C4100: “name”: 未引用的形参 2. gcc : warning: unused parameter 'name' 警告Q?未用的参数‘name’ 在gcc中,打开q个警告的选项?strong>-Wunused-parameter?br>该选项包含?Wall中?br> 三?
void greeting_nowarning( const char * name) { ( void )name; printf( " hello OwnWaterloo\n " ); }
在C和C++中都正确Qƈ且无警告?br>
相关链接Q?br> ——示例代?br>http://immature.googlecode.com/svn/trunk/iMmature/sample/omit_parameter_name
?span rel="dc:type" xmlns:dc="http://purl.org/dc/elements/1.1/">作品 采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?6?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_parameter_name.html
]]>main函数中省略返回语?/title> http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_return_in_main.htmlOwnWaterloo OwnWaterloo Sun, 26 Apr 2009 06:37:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_return_in_main.html http://www.shnenglu.com/ownwaterloo/comments/81116.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_return_in_main.html#Feedback 1 http://www.shnenglu.com/ownwaterloo/comments/commentRss/81116.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/81116.html 一、依?br> C++标准规定Qmain函数可以省略q回语句Q等效于q回0?br> 5. A return statement in main has the effect of leaving the main function (destroying any objects with automatic storage duration) and calling exit with the return value as the argument. If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
——ISO C++03 3.6.1 Main function p44/72 ——ISO C++98 3.6.1 Main function p43/69 注意Q?br>1. main函数的返回类型是int Q?不是void或者其他类型?br>2. 该规?strong>仅仅对main函数适用?br>3. 对其他函敎ͼ如果省略q回| 得C?strong>警告?br>4. 应该避免 3的情c?br>
二?nbsp;CZ 二?. 一个合法的最化的完整C++E序如下Q?
int main() {}
二?. 省略的确切含?br> 同时Q标准中的用语是?strong>考究的: “当控制到达mainl束处时没有遇到return语句Q效果与q回0相同”?br> x_标准规定的是“对省略return?strong style="COLOR: #ff0000">分支Q认?”?br>同时Q标准也允许其他分支 含有q回语句?br>如下Q?
int main( int argc, char * []) { switch (argc) { case 1 : // error, should passing argument return - 1 ; // parse arguments default : case 3 : // parser argv[2] case 2 : // parser argv[1] ; } // do some work // control reaches here }
没有输入命o行参数时Q?q回一个错误?br>其他情况Q当控制辑ֈmain?strong>l尾处时Q效果同return 0; 二?. 对于其他函数Q没有这U?#8220;优待” 如:
int not_main( int argc) { if (argc <= 1 ) return - 1 ; } int main( int argc, char * []) { return not_main(argc); }
not_main无疑得C个警告?br>E序在没有输入命令行参数时的q回值将无法 预知 ?br>
三、验?br> 三?. ERRORLEVEL windows下,可以通过 %ERRORLEVEL % 查询上一ơ程序返回倹{?br> l果与判断相dQ?br>1. minimalist?strong>定的返回? 2. omit_return_in_main?strong>定的返回?1? 3. 对omit_return_in_other 3.1 有命令行参数Ӟq回?strong>定??br>3.2 无命令行参数Ӟq回?strong>无法 预知?
三? 汇编代码 更严谨的验证Ҏ是查看汇~代码?br> 可以看到Q在minimalist与omit_return_in_main的main函数中都有将eax|?的代码?br>在omit_return_in_other中的not_main函数中,没有q样的代码?/p>
四?nbsp;例外VC6 在这点上与标准不W?br> 四?. 对omit_return_in_mainQ它l出的警告: warning C4715: 'main' : not all control paths return a value 说明它在q点上与标准不符?br>昄Q在有命令行参数的时候,E序l果无法 预知 ?br> 四?. 对minimalistQ它l出的警告很搞笑Q?br> warning C4508: 'main' : function should return a value; 'void' return type assumed 暴露出它另一?strong>与标准不W?/strong>的地方——mainq回void?br>昄QQ何情况下Q程序结果都无法预知 ?br> 四?. 对omit_return_in_otherQ是E序员的错误?br>
五?实践 不知道ؓ什么C++标准在这里开一?#8220;后门”?br>——C++在许多地斚w是很严} 的?br> 在实际应用中Q尽量不要采用这一Ҏ, 因ؓQ?br>1. 旧编译器不支?br>2. C不支持——如果希望main能同时按C语言~译的话 对于演示 用的C++代码Q与主题无关的代码行能省则省Q则可以使用q一Ҏ?br>比如QC++标准中的CZ代码几乎都采用了q一Ҏ?br>由此可得出,C++标准在这里开后门的原因是——让C++标准更薄^_^
相关链接Q?br> ——示例代?br>http://immature.googlecode.com/svn/trunk/iMmature/sample/omit_return_in_main
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?6?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/26/omit_return_in_main.html
]]>可变长参数列表误Z陷阱——va_arg不可接受的类?/title> http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.htmlOwnWaterloo OwnWaterloo Tue, 21 Apr 2009 15:41:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html http://www.shnenglu.com/ownwaterloo/comments/80655.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html#Feedback 5 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80655.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80655.html 例如Q我们要实现一个简易的my_printfQ?br>1. 它只q回voidQ?不记录输出的字符数目 2. 它只接受"%d"按整数输出?%c"按字W输出?%%"输出'%'本n 如下Q?br>
1 #include < stdarg.h > 2 3 void my_printf( const char * fmt, ... ) 4 { 5 va_list ap; 6 va_start (ap,fmt); /* 用最后一个具有参数的cd的参数去初始化ap */ 7 for (; * fmt; ++ fmt) 8 { 9 /* 如果不是控制字符 */ 10 if ( * fmt != ' % ' ) 11 { 12 putchar( * fmt); /* 直接输出 */ 13 continue ; 14 } 15 /* 如果是控制字W,查看下一字符 */ 16 ++ fmt; 17 if ( ' \0 ' ==* fmt) /* 如果是结束符 */ 18 { 19 assert( 0 ); /* q是一个错?nbsp; */ 20 break ; 21 } 22 switch ( * fmt) 23 { 24 case ' % ' : /* q箋2?%'输出1?%' */ 25 putchar( ' % ' ); 26 break ; 27 case ' d ' : /* 按照int输出 */ 28 { 29 /* 下一个参数是intQ取?nbsp; */ 30 int i = va_arg (ap, int ); 31 printf( " %d " ,i); 32 } 33 break ; 34 case ' c ' : /* 按照字符输出 */ 35 { 36 /* * 但是Q下一个参数是char?/span> */ 37 /* 可以q样取出?/span>Q?nbsp; */ 38 char c = va_arg (ap, char ); 39 printf( " %c " ,c); 40 } 41 break ; 43 } 44 } 45 va_end (ap); /* 释放 ap—?必须Q?/font> ?strong>相关链接 */ 46 }
q与《C++E序设计语言》中的一道练习题很类伹{?br>——需要支?%c"控制W?br> 在《C++E序设计语言-题解》中Q给Z一个答案(中文p65)?br>但是Q?如同上面的代码一?/strong>Q它们都?strong style="COLOR: #ff0000">错误 的!
单的_我们?span style="COLOR: #ff00ff">va_arg(ap ,type )取出一个参数的时候,type l?/span>对不能ؓ 以下cdQ?br>—?span style="COLOR: #0000ff">char ?span style="COLOR: #0000ff">signed char ?span style="COLOR: #0000ff">unsigned char —?span style="COLOR: #0000ff">short ?span style="COLOR: #0000ff">unsigned short —?span style="COLOR: #0000ff">signed short ?span style="COLOR: #0000ff">short int ?span style="COLOR: #0000ff">signed short int ?span style="COLOR: #0000ff">unsigned short int —?span style="COLOR: #0000ff">float 一个简单的理由是: —?strong>调用?span style="COLOR: #ff0000">l对?/span>?/strong>?span style="COLOR: #993300">my_printf传?/strong>以上cd?strong>实际参数 ?br> 在C语言中,调用一个不带原型声明的函数Ӟ 调用者会?strong>每个参数执行“默认实际参数提升 (default argument promotions )”?br> 同时Q对可变长参数列?strong>出最后一?/strong>?strong>cd声明的Ş式参?/strong>之后?strong>每一个实际参?/strong>Q也执行上q提升工作?br>提升工作如下Q?br>——floatcd的实际参数将提升到double ——char、short和相应的signed、unsignedcd的实际参数提升到int ——如果int不能存储原|则提升到unsigned int 然后Q调用者将提升?/strong>的参?strong>传?/strong>l被调用者?br>所以,my_printf?strong>l对无法接收?/strong>上述cd的实际参数的?br>
上面的代码的38?9行,应该改ؓQ?br>
int c = va_arg (ap, int ); printf( " %c " ,c);
同理Q?如果需要用short和floatQ?也应该这P
short s = ( short )va_arg(ap, int ); float f = ( float )va_arg(ap, double );
q也是printf族函数没有用于short和float的控制符的原因?br>
附录Q?br> 在《C语言E序设计》对可变长参数列表的相关章节中,q没有提到这个陷阱?br>但是有提到默认实际参数提升的规则Q?br> 在没有函数原型的情况下,char与shortcd都将被{换ؓintcdQfloatcd被转换为doublecd?br> ——《C语言E序设计》第2? 2.7 cd转换 p36 在其他一些书c中Q也有提到这个规则: 事情很清楚,如果一个参数没有声明,~译器就没有信息d它执行标准的cd查和转换?br>在这U情况下Q一个char或short作为int传递,float作为double传递?br>q些做未必是E序员所期望的?br>脚注Q这些都是由C语言l承来的标准提升?br>对于q略号表示的参敎ͼ其实际参数在传递之前L行这些提升(如果它们属于需要提升的cdQ,提升后的g递给有关的函数。——译者注 ——《C++E序设计语言》第3?特别?7.6 p138 …… floatcd的参C自动转换为doublecdQshort或charcd的参C自动转换为intcd …… ——《C陷阱与缺陗?4.4 形参、实参与q回?p73 q里有一个陷阱需要避免: va_arg宏的W?个参C能被指定?strong>char ?strong>short或?strong>floatcd?br>因ؓchar和shortcd的参C被{换ؓintcdQ而floatcd的参C被{换ؓdoublecd …… 例如Q这样写肯定是不?/strong>的: c = va_arg(ap,char); 因ؓ我们无法传递一个charcd参数Q如果传递了Q它会被自动{化ؓintcd。上面的式子应该写成Q?br>c = va_arg(ap,int); ——《C陷阱与缺陗p164
2009/05/07 修改Q?br>printf函数族有用于short的控制符“h”?br>见:http://www.cplusplus.com/reference/clibrary/cstdio/printf/
相关链接Q?br> ——《可变长参数列表误区与陷阱——va_end是必ȝ吗??br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html
?span rel="dc:type" xmlns:dc="http://purl.org/dc/elements/1.1/">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可?
转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?1?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html
]]> 可变长参数列表误Z陷阱——va_end是必ȝ吗? http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.htmlOwnWaterloo OwnWaterloo Tue, 21 Apr 2009 07:53:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html http://www.shnenglu.com/ownwaterloo/comments/80616.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html#Feedback 2 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80616.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80616.html q本应是一个无M论的问题——当然必调用?br> stdargQ或varargsQ下略)中提供的功能是一U?strong style="COLOR: red">契约Q?br>“你按我的U定方式使用q些?br>——即必须 调用 va_end ——我q你提供实现可变长参数列表所需要的功能?#8221; 使用stdarg本来?strong>?span style="COLOR: red">?/span>的事?br>—?strong>按照一个简单的契约 Q另见相关链接)办事 可以了 ——根本无M解其具体实现?br> 有h乐意ȝI该功能是如何实现的Q?也很好?br> 可是某些?br>——或通过研究其的实现Q或通过实践 ——发C所使用的^CQ?va_end是可以忽略的?br>之后Q他开始大攑֎?Q?“va_end是不必要的!” 由此Q?造成一些不必要的误解与争论?br>
让我们看看对va_end的两U态度Q?br>
一?va_end能省则省Q?br> 假设你用的某个C/C++~译器,提供的va_end是可忽略的?br>比如msvc中的va_end的实现如下:
#define va_end (ap ) ap = (va_list )0 /* ap|空 */
通常直接使用va_start的函敎ͼ假设?strong>fQ的实现体会很短 。: 1. ?span style="COLOR: #ff00ff">va_start初始?span style="COLOR: #0000ff">va_list 2. 调用一个?strong>va_list参数的函敎ͼ假设?strong>vfQ?br>Qvf 是一个固定参数列表的函数Q?br> 因ؓf的实C非常短, 一眼望Iѝ?br>所以你能确保vfq回后, ap不会再被你用?br> 因此Q?ap|空除了费CPU周期Q?没有实际意义Q?是这样吗Q?br> 一?. ~译器参与优?br> 你能发现代码末尾ap不再被用, va_end其|空毫无意义?br>那么Q你的编译器能发现这个问题么Q?br> h证一下?br>如果~译器也知道Q?q且没有为va_end生成M代码Q?那么省略va_end是不必要的了?br> 一?. ~译器不参与优化 你编译器真ؓva_end生成了无意义q且令h感到无法接受的机器码Ӟ该怎么办? 一?.1 你只在该~译器下工作 那么Q你省略va_end好了?br>但请不要宣扬一些带?strong>误导 性质的言辞?br>当你?#8220;va_end是不需?#8221;的时候, 请附带说明: 1. 你的q_ 2. ?strong>?/span>考虑跨^?/strong> 一?.2 需要要考虑UL到其他编译器注意 Q?其他~译器包括(但不限于Q: ——不?strong>架构上的~译?br>——相同架构上的不?strong>~译器?/strong> ——相同架构上的相同编译器产品?strong>不同版本?br> 需要分析在该编译器下,对va_end的处理是?strong>依然可以被省?/strong>?br>——显Ӟq是一?strong>乏味的工作?br> 即你在源代码中写入 Q?/p>
/* va_end is trivial, omit it */
也难保它不会?span style="COLOR: #ff0000">遗忘
—?UL一个程序的时候有太多工作 要做?br>q么一个不L的地方, 会被惌v来么Q?br> 如果在被UL的编译器上: 1. 省略va_end导致函C能正常返回(见附录) 也许立马p发现q个bug?br>崩掉了嘛Q?当然要引?#8220;重视”?br> 2. 省略va_end不会立马崩溃Q?而是D内存泄露Q见附录Q?br>情况很严重 了?br>E序依然q行“良好”?br>但是调用一ơ函敎ͼ 泄漏一点点内存?br> q恐怕就要花很多旉才能查出来了?br>如果目旉再紧一点, 也许Ҏ来不及修复q个bug发布了?br>反正漏得?#8220;不多”Q?你说是吧Q?br>
二?va_end能留则留 我们何不换个方式Q? 1. 坚持使用va_end ——即便我们心里清楚它没做什么有用的事情也是如此?br> 代码UL本质是Q?不对q_QCPU、OS、Compiler{等Q?span style="COLOR: #ff0000">依赖 ?br>stdarg是标准库提供的一U实现可变长参数列表?strong style="COLOR: #ff0000">可移?/strong>方式?br>我们没理由弃之不用?br> 如果我们在源代码中坚持用va_endQ?br>——至在q点上,׃?strong>对编译器产生依赖Q?strong>省略va_endQ就是一U?span style="COLOR: #ff0000">依赖 Q?br>——移植的时候, 自然无须为其操心?br> 2. va_end令编译器产生?strong>令h无法接受 ?strong style="COLOR: #ff0000">无用代码?br>——通常Q这是不会发生的?~译器厂商会考虑q个事情?br> 比如上面的va_end宏, 会生一ơ不必要的赋值操作, 但通常会被~译器优化ؓI?br>即没有被优化ؓI, 一ơ赋值操作, 真的是不可容忍 的么Q?br> 如果实不能容忍Q?作ؓ一U?strong>Ҏ 情ŞQ?可以q样 Q?/p>
#if defined (COMPILER1 ) || defined (COMPILER2 ) || ... /* * special situation the machine code generated by these compliers is unacceptable , omit it */ #else /* general situation */ va_end (ap );#endif
附录 —?看看大牛们是怎么说的?br> 从一个用过va_start()的函C退Z前,必须 调用一ơva_end()?br>q是因ؓva_start可能 以某U方?strong>修改了堆?/strong>Q这U修改可能导?strong>q回无法完成 Qva_end()能将有关的修改复原?br> ——《C++E序设计语言?W?版、特别版Q?p139 ——即上面提到?“立即崩溃”?br> 我们务必CQ在使用完va_list变量后一定要调用宏va_end?br>?strong>大多?/strong>C实现上,调用va_end?strong>否ƈ无区?/strong>?br>但是Q?strong>某些版本的va_start宏ؓ了方便对va_list的遍历,q参数列表动态分配内?/strong>?br>q样一UC实现很可能利用va_end宏来释放此前动态分配的内存Q?br>如果忘记调用宏va_endQ最后得到的E序可能在某些机型上没有问题Q而在另一些机型上则发?#8220;内存泄露 ”?br> ——《C陷阱与缺陗, p161 ——即上面提到?#8220;内存泄露”?br> …… 最后,必须 在函数返回之?strong>调用 va_endQ以完成一些必要的清理 工作?br> ——《CE序设计语言?W?版, p137 ……在所有参数处理完毕后Q?且在退出函数f之前 Q?strong>必须调用宏va_end一?/strong> …… ——《CE序设计语言?W?版, p232
相关链接Q?
——可变长参数列表误区与陷阱——va_arg不可接受的类?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html q是使用stdarg提供的功能需要遵守契U之一?br>契约本n仍然是简单的?br>契约背后的原理也许比较晦涩, 但也可以不必兛_?br>
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?1?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html
]]> ~译器选项——语a http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/compiler_options_language.htmlOwnWaterloo OwnWaterloo Mon, 20 Apr 2009 07:02:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/compiler_options_language.html http://www.shnenglu.com/ownwaterloo/comments/80538.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/compiler_options_language.html#Feedback 0 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80538.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80538.html 一?l一的预处理、编译、链接程?br> 一?. 有些E序同时h如下功能Q?br> 1. 预处理C/C++源代?br>2. ~译C/C++源代?br>3. 链接C/C++目标代码 例如QGCC的gcc、g++QMSVC的cl.exe?br> 一?. 实际的情况也许更加复杂: gcc、g++、cl.exe很有可能只是一?strong>启动?/strong>?br>用户只需要用它们, 它们内部再根?strong>特定 条gQ?执行其他E序Q比如: 1. gcc、g++~译C/C++代码Ӟ 最l会执行cc1 /cc1plus E序?br>该程序可能才是真正的C/C++~译器?br> 2. gcc、g++在链接C/C++目标代码Ӟ最l会执行ld E序?br>该程序可能才是真正的链接器?br> 3. cl.exeE序自己处理C/C++代码的预处理与编译工作?br> 4. cl.exeE序链接Ӟ执?strong>link.exe?br>该程序可能才是真正的链接器?br> 一?. 我们的关注点 ——上q复杂的情况我们大多数情况下无须操心Q?br> 1. 我们只需要用gcc、g++ 即以后GCCcc1、cc1plus、ld改ؓ别的名字也不会受影响?br> 2. 我们只需要用cl 即以后cl不再担Q~译工作或者link.exe被改为别的名字,同样不受影响?br> ——我们需要关心这些统一的程序,?strong>Ҏ何种条gQ?军_它们的操作的Q?br> 本文只讨论编译: 1. 它们默认 是通过何种条gQ?军_按C语法或按C++语法 ~译一个翻译单元的?br>2. 如何昑ּ指定 按C语法或者按C++语法ȝ译一个翻译单元?br>
二?默认情况 如果不显式指定操作, gcc、g++、cl都是按文件后~名来军_操作的?br> 二?. 试文gQ?
#ifndef __cplusplus /* being treated as C translation unit */ #error !--- C ---! #else // being treated as C++ translation unit #error !--- C++ ---! #endif
我们Z个没有后~的文Ӟ叫nosuffixQ?写入如上内容?br>而且Q?我们也不需要编译出目标代码?br>只需要测试__cplusplus宏(见?a href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html">预定义__cplusplus?/strong>》)是否存在Qƈ且用#error报告卛_?br> 然后建立一些内容完全一L文gQ?/p>
#include " nosuffix "
q些文g共有10个: c.c?cpp.cpp、txt.txt、UC.C、UCPP.CPP、cc.cc、cxx.cxx、inl.inl、c++.c++、cp.cp?br>QUC和UCPP是ؓ了测试大写后~名) 二?. 试Ҏ 对GCC使用Q?br>gcc(g++) filename >stdout.txt 2>stderr.txt 对MSVC使用Q?br>cl filename >stdout.txt 2>stderr.txt 二?. 试l果 gcc、g++、cl对以下后~名文件的默认操作如下?/a>Q?br>
nosuffix
.c
.cpp
.txt
.C
.CPP
.cc
.cxx
.inl
.c++
.cp
gcc
obj
C
C++
obj
C++
C++
C++
C++
obj
C++
C++
g++
obj
C++
C++
obj
C++
C++
C++
C++
obj
C++
C++
cl
obj
C
C++
obj
C
C++
C++
C++
obj
obj
obj
对该表的几点说明Q?br>1. 表中的obj表示该条件下Q?l一E序它们认作目标文Ӟ q打执行链接工作?br>q显然是错误的, 因ؓ他们包含的是文本?br> 2. gcc、g++Q编译代码)的区?br>GCC认ؓ带有.c?cpp?C?CPP?cc?cxx?c++?cpQ但不限于)后缀的文件是C/C++源文件?br>gcc把带?c后缀的文Ӟ 当作C源文Ӟ 把带有其他后~名的文g当作C++源文件?br>g++带有上q所有后~的文Ӟ都当作C++源文件?br> 3. MSVC与GCC的区?br>MSVC认ؓ带有.c?cpp?C?CPP?cc?cxx后缀的文件是C/C++源文件?br>上述GCC相比Q?排除?c++?cp 同时Qwindows下的文g名是不区分大写的, 所?c?CQ?cpp?CPP是一L?br>与GCC相比Q?.C不再认ؓ是C++源文Ӟ 而是?c一样作为C源文件处理?br> 二?. 试结 ׃表以及说明, 如果我们打算~写跨^台的代码 Q?br> 1. 不推荐用的后缀?br>.c++?cp ——因为它们不被MSVC支持 .C ——因为MSVCq不区别对待.c?C 2. 可以使用的后~?br>——对C源文?br>可以使用.c?br> ——对C++源文?br>可以使用.cpp?cc?cxx?br> —?CPP不推?br>因ؓ在xnix?a.CPP与a.cpp?个文Ӟ 而复制到Windows上就发生重名?br>如果只?cpp可以避免该情况?br> 3. 关于.inl 有些文g内容实是C/C++代码Q?但是却不直接作ؓ译单元Q而是被其他翻译单元包含?br>理论上说Q它们取M名字都没关系。但是将它们取ؓ.inl会得C些好处: —?nbsp; 暗示该文件包含C/C++代码 —?nbsp; 一些编辑器会对其按C/C++语法q行高亮?br>
三?昑ּ指定 有时候需要覆盖默认情况,昑ּ指定我们需要的操作?br> 三?. GCC “-x ” GCC通过-x选项昑ּ指定~译源代码的语言Q?br>-x cQ或-xcQ?br> —?nbsp; 源代码作ؓC源文件?br>-x c++、(?xc++Q?br> —?nbsp; 源代码作ؓC++源文件?br> 对于“?#8221;中的试Q?只要命令行改ؓQ?br>gcc(g++) -x c (-xc) filename 所有文仉被作ؓC源文件处理, q输?error !--- C ---! 而用如下命令行Q?br>gcc(g++) -x c++ (-xc++) filename 所有文仉被作ؓC++源文件处理, q输?error !--- C++ ---! 三?. MSVC “/TC” “/TP” MSVC通过/TCQ?TPQ选项Q?昑ּ指定输入作为CQC++Q源代码?br> ?#8220;?#8221;中的试Q?命o行: cl /TC filename Ҏ有文仉输?error !--- C --- !
命o行: cl /TP filename Ҏ有文仉输?error !--- C++ ---!
四、ȝ 1. 使用“二?”中推荐的方式Q给源代码文件命名?br>2. 覆盖默认情况Q?x(GCC)或?TC?TPQMSVCQ?br>3. 带提一点, gcc、g++用作链接Ӟ 也有一些区别?br>链接C++Q或者C/C++混合Q目标代码, 推荐使用g++?br>因ؓGCC高版本中Q?gcc链接旉认不会导入C++需要的q行时库?br>
相关链接Q?br> ——源代码http://immature.googlecode.com/svn/trunk/iMmature/sample/compiler_options/language ——?a href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html">预定义__cplusplus?/a>?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?0?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/compiler_options_language.html
]]>
预定义__cplusplus?/title> http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.htmlOwnWaterloo OwnWaterloo Mon, 20 Apr 2009 06:42:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html http://www.shnenglu.com/ownwaterloo/comments/80537.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html#Feedback 0 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80537.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80537.html 一?介绍预定义宏"__cplusplus" 一.1 __cplusplus宏在C++标准中的描述如下Q?br> 16.8 Predefined macro names __cplusplus The name __cplusplus is defined to the value 199711L when compiling a C++ translation unit.143) 143) It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming compilers should use a value with at most five decimal digits . —?ISO C++03 p315 —?ISO C++98 p309 如果一D代码是需要针对C++~写的, 可以使用该宏q行条g~译?br> 一.2 __cplusplus的值是Z 表示C++的版?br> 一.3 __cplusplus的类型是"long int" ——这是理Z的?br>现在发布的C++标准只有C++98Q?C++03是C++98?strong>修订Q?内容只有很少改变?br>所以在ISO C++03中, 也规定该宏的值是199711LQ这是一?strong>长整数字面?/strong>Q?br> ——实际上Q?目前不应?span style="COLOR: red">依赖?/strong>宏的| 因ؓQ?br>1. 目前标准中规定的值只有一个—?99711LQ?没有Ҏ该D行条件编译的可能?br> 2. 目前C++~译器ƈ不一?strong>按标准实?/strong>q个宏(见测试)?br>
二?试预定义宏__cplusplus CZ1Q?
#include < stdio.h > int main() { #define TO_LITERAL(text) TO_LITERAL_(text) #define TO_LITERAL_(text) #text #ifndef __cplusplus/* this translation unit is being treated as a C one */ printf(" a C program\n " ); #else // this translation unit is being treated as a C++ one printf( " a C++ program\n__cplusplus expands to \ "" TO_LITERAL(__cplusplus) " \ " \n " ); #endif (void )getchar(); return 0 ; }
代码很简单: 如果没有定义__cplusplusQ?那么当前源代码被当作C源代码处理?br>如果定义了__cplusplusQ那么当前源代码被当中C++源代码处理, q且输出__cplusplus宏被展开后的字符丌Ӏ?br> CZ2Q?/p>
__cplusplus
q段代码更简单了Q?只是使用了__cplusplus宏?br>然后查看预处理(见?a href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html">查看源文仉处理l果 》)Q看其被扩展后的l果?br>
三?试l果 ——msvc8 ——msvc9 __cplusplus按照标准被扩展ؓ—?99711L?br> ——msvc6 ——gcc (GCC) 3.4.2 (mingw-special) ——gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu3) __cplusplus只是单的被扩展ؓ—??br> q也说明了不应该依赖__cplusplus宏的倹{?br>
相关链接Q?br> ——源代码http://immature.googlecode.com/svn/trunk/iMmature/sample/predefined_macro/__cplusplus ——?a href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html">查看源文仉处理l果?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?0?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/20/predefined_macro___cplusplus.html
]]> 预定义__GNUC__?/title> http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/predefined_macro___GNUC__.htmlOwnWaterloo OwnWaterloo Thu, 16 Apr 2009 12:07:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/predefined_macro___GNUC__.html http://www.shnenglu.com/ownwaterloo/comments/80178.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/predefined_macro___GNUC__.html#Feedback 0 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80178.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80178.html 一?介绍预定义宏“__GNUC__” 一.1 __GNUC__ 是gcc~译器编译代码时预定义的一个宏?br> 需要针对gcc~写代码Ӟ 可以使用该宏q行条g~译?br> 一.2 __GNUC__ 的DCgcc的版本?br> 需要针对gcc特定版本~写代码Ӟ也可以用该宏进行条件编译?br> 一.3 __GNUC__ 的类型是“int” 该宏被扩展后Q?得到的是整数字面?/strong>?br>可以通过仅预处理 Q查看宏扩展后的文本 。见Q?strong>查看源文仉处理l果 ?br>同时下面的示例也能体现出q一炏V?br>
二?试预定义宏__GNUC__ CZQ?
#include < assert.h > #include < stdio.h > #include < typeinfo > #ifndef __GNUC__#error sample for gcc compiler #else /* use gcc special extension: #warning , __attribute__, etc. */ #endif int main() { printf( " hello gcc %d\n " ,__GNUC__); assert( typeid(__GNUC__) == typeid( int ) ); printf( " press Enter to exit\n " ); ( void )getchar(); }
修改Q?br> —?009/04/18 __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ These macros are defined by all GNU compilers that use the C preprocessor: C, C++, and Objective-C. Their values are the major version, minor version, and patch level of the compiler, as integer constants . For example, GCC 3.2.1 will define __GNUC__ to 3, __GNUC_MINOR__ to 2, and __GNUC_PATCHLEVEL__ to 1. They are defined only when the entire compiler is in use; if you invoke the preprocessor directly, they are not defined. —?http://gcc.gnu.org/onlinedocs/gcc-3.1.1/cpp/Common-Predefined-Macros.html#Common%20Predefined%20Macros
相关链接Q?br> ——源代码http://immature.googlecode.com/svn/trunk/iMmature/sample/predefined_macro/extension/__GNUC__/ ——《查看源文g预处理结果?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html ——《预定义_MSC_VER宏?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/predefined_macro__MSC_VER.html
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?6?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/predefined_macro___GNUC__.html
]]> 配置msvc命o行环?l?——编写msvc~译脚本 http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.htmlOwnWaterloo OwnWaterloo Wed, 15 Apr 2009 19:42:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html http://www.shnenglu.com/ownwaterloo/comments/80101.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html#Feedback 0 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80101.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80101.html 阅读全文 ]]> 查看源文仉处理l果 http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.htmlOwnWaterloo OwnWaterloo Wed, 15 Apr 2009 16:49:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html http://www.shnenglu.com/ownwaterloo/comments/80093.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/get_result_of_preprocessing.html#Feedback 4 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80093.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80093.html ~译C/C++源代码时Q源代码首先会被预处理器QpreprocessorQ进行预处理QpreprocessQ?br>预处理器执行源代码中?strong>预处理指?/strong>Q如Q?br>——文件包?br>#include ——条件编?br>#if?#ifdef?#ifndef?#elif?#else?#endif ——宏 #define?#undef、宏标识W、宏扩展 ——其?br>#error?line?pragma …… 预处理之后的l果Q即提交给~译器)与程序员看到的源代码也许会有很大的差?/strong>?br>其在源代码中含有许多错l复杂的宏与条g~译时?br>当我们被q些狂ؕ 的宏与条件编译折的时候, 如果能看到预处理的结果, 也许会有很大的帮助?br> 下面以一个示例说明msvc与gcc中得到预处理l果的方式?br>
零?CZ 假设我们需要查?_MSC_VER ?nbsp;__GUNC__ 两个宏最l被扩展出的文本Q?nbsp;
int main() { int result = #if defined(__GNUC__) __GNUC__#elif defined(_MSC_VER) _MSC_VER#else #error unknown compiler #endif ; return result; }
该程序很单, main函数q回一个resultQ然后立即退出?br>而result的| Ҏ条g~译得到Q?br>1. 如果是GCC~译器, 那么result赋gؓ__GNUC__ 2. 否则如果是VC~译器, 那么result赋gؓ_MSC_VER 3. 否则是一个未知的~译器, 错误 接下来, 我们来看看_MSC_VER与__GNUC__q?个宏最l到底被扩展Z么文本?br>
一?GCC 一.1?-E 选项 -E选项把预处理的l果Q写入stdout?br>也就是说Q?执行如下命oQ?br>gcc -E preporcess_only.c p在控制台中得到预处理后的l果 Q大致如下:
# 1 "../preprocess_only.c" # 1 "<built-in>" # 1 "<command line>" # 1 "../preprocess_only.c" int main() { int result =3 ; return result; }
可以看到Q?__GUNC__ 宏最l被扩展为整数字面量3QGCC 3Q?br> 如果源代码很长, 输出到命令行H口中查看也怸方便?br>如何其输出C个文件中呢? 一.1.1?重定?br> 因ؓ-E是输出到stdoutQ?昄可以其重定向到另一个文Ӟ 如执行如下命令: gcc -E preprocess_only.c >stdout.txt 那么stdout.txt中, p得到刚才命o行窗口中的内宏V?br> 一.1.2?-o Q小写) 选项 -o选项用于指定出文件名?br>对于-cQ?-o指定的是目标文g名?br>对于-S Q?o指定的是汇编文g名?br>对于-EQ?-o自然也可以指定预处理文g名, 如执行如下命令: gcc -E preprocess_only.c -o output.txt 那么output.txt中会得到“一.1.1”中的stdout.txt?#8220;一.1”中控制台H口一Ll果?br> 一.2?save-temps 选项
-save-temps选项保?strong>中间文g
Q如预处理后的结果文件、汇~代码文件与目标文g?br>其中的预处理l果文gQ通常?strong>.i后缀Q是我们所需要的?br> 举例Q?br>1?gcc -save-temps -E preprocess_only.c0 个中间文件?br>输出预处理结果, ?#8220;一.1”一P 输出到控制台H口中?br>Ҏ如下命oQ?br> 1.1?nbsp;gcc -save-temps -E preprocess_only.c -o temp_output.txt 1.2?gcc -save-temps -E preprocess_only.c >temp_output.txt 可以看出Q?-E选项不生中间文件?预处理结果就是最l结果?br>同时可以使用 -o选项或者重定向Q?把结果保存到一个文件中?br> 2?gcc -save-temps -S preprocess_only.c1 个中间文Ӟ preprocess_only.iQ预处理l果Q?br>1个输出文Ӟpreprocess_only.sQ汇~代码) Ҏ如下命oQ?br> 2.1?gcc -save-temps -S preprocess_only.c -o unknown 得到preprocess_only.i文gQ内Ҏ预处理结果,是中间文件?br>得到unknown文gQ内Ҏ汇编代码Q?是最l结果文件?br> 3?gcc -save-temps -c preprocess_only.c2 个中间文Ӟ preprocess_only.i与preprocess_only.s?br>1个输出文Ӟ preprocess_only.oQ目标代码) Ҏ如下命oQ?br> 3.1?gcc -save-temps -c preprocess_only.c -o unknown 得到preprocess_only.i ?preprocess_only.s文gQ内容分别是预处理结果与汇编代码Q是中间l果?br>unknown文gQ?内容是目标代码,是最l结果文件?br> 4?gcc -save-temps preprocess_only.c3 个中间文Ӟ preprocess_only.i、preprocess_only.s、preprocess_only.o?br>1个输出文Ӟ a.outQa.exe with mingwQ?br>Ҏ如下命oQ?br> 4.1?gcc -save-temps preprocess_only.c -o what 得到上述3个文Ӟ 是中间文件?br>what文gQwhat.exe with mingwQ, 内容是可执行代码Q?是最l结果文件?br>
二?MSVC VC6??中与查看预处理相关的选项可以通过如下命o查看Q?br>cl /help 在输ZQ?nbsp;?-PREPROCESSOR- q个cd?br>其中与预处理l果相关的有如下一些选项Q?br> ?1?E 选项 /E preprocess to stdout /E 预处理定向?stdout 昄Q?q和“一.1”是等LQ?如: cl /E preprocess_only.c 在命令行H口中将得到cMl果 Q?
#line 1 "preprocess_only.c" int main() { int result = #line 6 "preprocess_only.c"1200 #line 10 "preprocess_only.c" ; return result; }
可以看到Q?_MSC_VER宏最l被扩展为整数字面?200QVC6Q?br> 对于较长的源文gQ?我们同样希望结果输出到一个文件中?br> ?1.1、重定向 执行Q?br>cl /E preprocess_only.c >stdout.txt stdout.txt保存上面的l果?br> 注意Q?在msvc中,没有“一.1.2”的对应物?br>执行Q?br>cl /help 在输Z扑ֈ-OUTPUT FILES-cdQ?可以看到没有命名预处理结果的方式。有两个怼的选项Q?br>/Fe 命名可执行文件?br>/Fp 命名预编译头文g?br>但不是我们需要的选项?br> 也许VC认ؓ通过 “/E + 重定?#8221;可以达到命名输出文件的目的?br>所以就没有设计辑ֈ此目的的另一U方法?br> ?2?P 选项 /P preprocess to file /P 预处理到文g 执行Q?br>cl /P preprocess_only.c 得?preprocess_only.i /P会将?nbsp;xxx.suffix 的预处理l果输出?xxx.i 文g中?br>没有指定文g名的方式 ?如果需?strong>指定输出文g?/strong>Q?可以使用 “/E + 重定?#8221; ?3 /EP 选项 /E?P选项都将保留一部分Q源文gQ行信息Q如“?1”所C?br>如果q是不需要的Q?可以使用 /EP选项?br> /EP preprocess to stdout, no #line /EP 预处理到标准输出Q没?#line 如: cl /EP preprocess_only.c 得到如下输出:
int main() { int result = 1200 ; return result; }
同样Q?如果需要输出到指定文gQ?可以使用重定?/strong>?br> ?4 其他一些有的选项 1. /C Q大写) don't strip commentsQ不抽出注释Q?br>如果保留注释对理解预处理l果有帮助, 可以使用q个选项?br> 2. /U /u /u remove all predefined macros /u U除所有预定义的宏 /U<name> remove predefined macro /U<name> U除预定义的?br> 比如可以通过Q?br>cl /u preprocess_only.c cl /U_MSC_VER preprocess_only.c 来得C?unknown complier错误?#8230;… 3. /D /D<name>{=|#}<text> define macro /D<name>{=|#}<text> 定义?br> 可以通过Q?br>cl /D__GUNC__=3 preprocess_only.c 来假装gcc~译器囧……
相关链接Q?br> ——示例文件下?br>http://immature.googlecode.com/svn/trunk/iMmature/sample/compiler_options/preprocess_only/ http://www.shnenglu.com/Files/ownwaterloo/preprocess_only.zip ——《配|msvc命o行环境?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/environment_for_using_cl_from_command_line.html ——《配|msvc命o行环?l?——编写msvc~译脚本?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html ——《预定义_MSC_VER宏?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/predefined_macro__MSC_VER.html ——《预定义__GNUC__宏?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/predefined_macro___GNUC__.html
?span xmlns:dc="http://purl.org/dc/elements/1.1/" rel="dc:type">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可? 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?6?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/preprocess_only.html
]]> 配置msvc命o行环?/title> http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/environment_for_using_cl_from_command_line.htmlOwnWaterloo OwnWaterloo Wed, 15 Apr 2009 13:29:00 GMT http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/environment_for_using_cl_from_command_line.html http://www.shnenglu.com/ownwaterloo/comments/80059.html http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/environment_for_using_cl_from_command_line.html#Feedback 0 http://www.shnenglu.com/ownwaterloo/comments/commentRss/80059.html http://www.shnenglu.com/ownwaterloo/services/trackbacks/80059.html 有些时候用命令行而不是IDEȝ译源代码会比较方ѝ?br>而在命o行下使用msvc的编译器——clQ?需要ؓ光|?strong>环境?br>
一?环境变量试 试cl的环境是否配|妥当, 可以执行如下试Q?br>win?R 启动q行 -> 输入cmdQwinntpdQ或者commandQwin95pdQ?-> 回RQ?打开命o行窗口?br>键入"cl"q回车, 如果有类似如下的输出 Q?br> -------------------------------------------------------------------------------- Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12 .00.8168 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] -------------------------------------------------------------------------------- Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14 .00.50727.42 for 80x86 Copyright (C) Microsoft Corporation. All rights reserved. usage: cl [ option... ] filename... [ /link linkoption... ] -------------------------------------------------------------------------------- 用于 80x86 ?Microsoft (R) 32 ?C/C++ 优化~译?15 .00.30729.01 ?br>版权所?C) Microsoft Corporation。保留所有权利?br> 用法: cl [ 选项... ] 文g?.. [ /link 链接选项... ]
-------------------------------------------------------------------------------- 一般来_ 可以在命o行下使用cl了?br> cl文g版本与VS版本、VC产品版本、_MSC_VER宏的对应关系如下?/a>Q?/p>
VS版本
VC产品版本?/p>
cl文g版本?/p>
_MSC_VER宏的?/p>
98
6.x
12.x
1200
2005
8.x
14.x
1400
2008
9.x
15.x
1500
二?试p| 如果出现Q?br>1. “cl不是内部或外部命令,也不是可q行的程序或批处理文件?#8221; 说明cl不在Path环境变量中?br> 2. 找不到xxx.dll?br>cl在Path环境变量中, Path中缺必要的dll的\径?br> 3. 上述试通过Q?但是在编译时出现找不到头文g或者库?br>说明Path环境变量中有cl和必要dll的\径, 但是仍缺其他一些环境变量?br> q些情况Q?都需要进一步配|环境变量?br>
三?配置环境变量 ?1 、让安装包帮助注册环境变?br> VC6在安装的时候,会弹Z个对话框Q让你选择是否注册VC6的环境变量。如下: For your convenince, the environment variables required to run build tools from a command prompt are saved in the VCVARS32.BAT in your BIN directory Q复选框Q?nbsp;Register Environment Variables Turn on this option to register environment variables for running Visual C++ tools from the command line. 默认复选框是没有选中的?br>如果选中Q?安装完毕后就会添加必要的环境变量?br> 所以, 一个办法是重新安装VC6Q反正很,相对于VC8?安装十分快速)?br> ?2 ?a id=vc6env>手工d环境变量 以VC6举例Q我们可以在 Q?#8220;我的电脑” -> “属?#8221; -> “高” -> “环境变量”中添加如下变量: %Path%="prefix \Microsoft Visual Studio\VC98\Bin";%Path% cl.exe所在\径?br> %include%="prefix \Microsoft Visual Studio\VC98\Include";%include% %lib%="prefix \Microsoft Visual Studio\VC98\Lib";%lib% C/C++以及Platform SDK %include%="prefix \Microsoft Visual Studio\VC98\MFC\Include";%include% %lib%="prefix \Microsoft Visual Studio\VC98\MFC\Lib";%include% MFC %include%="prefix \Microsoft Visual Studio\VC98\ATL\Include";%include% ATL Q其中的prefix 是安装目录的前缀Q之后就可以在命令行中用cl了?br> 同时Q?VC6??都提供了一个批处理vcvars32.bat ?br>我们可以查看相应的vcvars32.bat最l做了什么工作,而手工加入需要的变量?br>下内Ҏ自我机器上的vs vars32.batQVC8?的vcvars32.bat最l调用它们)Q?br>
vc8 @set PATH = D:\Program Files\Microsoft Visual Studio 8 \Common7\IDE;D:\Program Files\Microsoft Visual Studio 8 \VC\BIN;D:\Program Files\Microsoft Visual Studio 8 \Common7\Tools;D:\Program Files\Microsoft Visual Studio 8 \Common7\Tools\bin;D:\Program Files\Microsoft Visual Studio 8 \VC\PlatformSDK\bin;D:\Program Files\Microsoft Visual Studio 8 \SDK\v2. 0 \bin;C:\WINDOWS\Microsoft.NET\Framework\v2. 0.50727 ;D:\Program Files\Microsoft Visual Studio 8 \VC\VCPackages; % PATH % @set INCLUDE= D:\Program Files\Microsoft Visual Studio 8 \VC\ATLMFC\INCLUDE;D:\Program Files\Microsoft Visual Studio 8 \VC\INCLUDE;D:\Program Files\Microsoft Visual Studio 8 \VC\PlatformSDK\include;D:\Program Files\Microsoft Visual Studio 8 \SDK\v2. 0 \include; % INCLUDE % @set LIB= D:\Program Files\Microsoft Visual Studio 8 \VC\ATLMFC\LIB;D:\Program Files\Microsoft Visual Studio 8 \VC\LIB;D:\Program Files\Microsoft Visual Studio 8 \VC\PlatformSDK\lib;D:\Program Files\Microsoft Visual Studio 8 \SDK\v2. 0 \lib; % LIB % @set LIBPATH= C:\WINDOWS\Microsoft.NET\Framework\v2. 0.50727 ;D:\Program Files\Microsoft Visual Studio 8 \VC\ATLMFC\LIB
vc9 @set PATH = D:\Program Files\Microsoft Visual Studio 9.0 \Common7\IDE;D:\Program Files\Microsoft Visual Studio 9.0 \VC\BIN;D:\Program Files\Microsoft Visual Studio 9.0 \Common7\Tools;C:\WINDOWS\Microsoft.NET\Framework\v3. 5 ;C:\WINDOWS\Microsoft.NET\Framework\v2. 0.50727 ;D:\Program Files\Microsoft Visual Studio 9.0 \VC\VCPackages; % PATH % @set INCLUDE= D:\Program Files\Microsoft Visual Studio 9.0 \VC\ATLMFC\INCLUDE;D:\Program Files\Microsoft Visual Studio 9.0 \VC\INCLUDE; % INCLUDE % @set LIB= D:\Program Files\Microsoft Visual Studio 9.0 \VC\ATLMFC\LIB;D:\Program Files\Microsoft Visual Studio 9.0 \VC\LIB; % LIB % @set LIBPATH= C:\WINDOWS\Microsoft.NET\Framework\v3. 5 ;C:\WINDOWS\Microsoft.NET\Framework\v2. 0.50727 ;D:\Program Files\Microsoft Visual Studio 9.0 \VC\ATLMFC\LIB;D:\Program Files\Microsoft Visual Studio 9.0 \VC\LIB; % LIBPATH %
可以Ҏ它们Q给VC8?讄环境变量?br> ?3 、用vcvars32.bat 上面提到vcvars32.batQ它们的位置如下Q?br> VC6 prefix \Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT VC8 prefix \Microsoft Visual Studio 8\VC\bin\vcvars32.bat VC9 prefix \Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat 需要注意的是: q些批处理文件只会在当前q程 中设|(局部的Q环境变量,也就是说Q?br> 1. 用cmdQ或者commandQ打开的命令行H口中, q行某个vcvar32.bat一ơ?br>那么当前命o行窗口中可以正怋用clQ直到关闭?br> 2. 写批处理文g需要?strong style="COLOR: red">call prefix \vcvars32.batQ而不是直接启动vcvars32.bat?br>前者ؓ当前q程Qcpl.bat创徏的进E)d局部于q程环境变量?br>后者启动一个进E, 为其加入环境变量Q?然后该进E立即退出——没有Q何作用?br> ?4?使用VSXXCOMNTOOLS变量QVC8?Q?br> 对于VC8?有另一U方式——不注册全局的(pȝ或当前用P环境变量Q仅为当前进E设|(局部的Q环境变量?br>因ؓVC8?都可?strong>很方?/strong>的ؓ单个q程讄环境变量?br> 观察vc8和vc9的vcvars32.bat的内容(位置见上Q, 发现它们都只有一行: "%VS 80COMNTOOLS%vs vars32.bat" "%VS 90COMNTOOLS%vs vars32.bat" VS80COMNTOOLS、VS90COMNTOOLSQ注意不是VC而是VSQ分别是VS2005和VS2008安装后会讄的环境变量?br>所以我们也可以在自q批处理中Q很方便的ؓ当前q程讄需要的环境变量。如下: call "%VS80COMNTOOLS% vsvars32.bat" 以下cl命o执行VC8的cl?br> call "%VS90COMNTOOLS% vsvars32.bat" 以下cl命o执行VC9的cl?br>
四?ȝ 如果仅需要用某个版本的VCQ?q且只ؓ自己方便而用命令行Q?可以使用上面M一U方式?br>单归U_下: 1?使用全局环境变量——在pȝ或当前用户变量中加入需要的倹{?br> 1.1 重新安装 1.2 手工加入 2?不用全局环境变量 ——在执行cl前,先用对应的vcvars32.batQ命令行H口中执行或者脚本中call prefix\vcvars32.batQ?br> 2.1 vcvars32.bat加入Path变量 2.2 使用"%VS XX COMNTOOLS%vs vars.bat" (VC8?Q?或?absolutePath\vcvars32.bat 如果需要用多个版本的VC?或者需要将~译脚本发布l客户用, ׃能这么随意了?br>具体见:?a class=titlelink id=Editor_Results_rprSelectionList_ctl01_LinkTitle href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html">配置msvc命o行环?l?——编写msvc~译脚本 ?br>
相关链接Q?br> ——?a href="http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html">配置msvc命o行环?l?——编写msvc~译脚本 ?br>http://www.shnenglu.com/ownwaterloo/archive/2009/04/16/write_compile_script_for_msvc.html
——?a >IDE 不是E序员的唯一选择Q一Q?/strong>?br>http://blog.codingnow.com/2008/09/replacement_of_ide_1.html
?span rel="dc:type" xmlns:dc="http://purl.org/dc/elements/1.1/">作品采用知识׃n|名-非商业性?相同方式׃n 2.5 中国大陆许可协议 q行许可?br> 转蝲h?Q?br>文章作?- OwnWaterloo 发表旉 - 2009q?4?5?br>原文链接 - http://www.shnenglu.com/ownwaterloo/archive/2009/04/15/environment_for_using_cl_from_command_line.html
]]>
aëƬþ |
þþþþþƷþþþ |
ŷ龫Ʒþþþþþþžž |
ŷһþþƷ |
þ66͵Ʒ9 |
þþþùһëƬ |
ձŷþþþѲ |
Ʒþþþһ |
˾þþƷһ
|
99þѹػ |
ŷҹAŴƬþ |
þþWWW˳ɾƷ |
Ʒһþ㽶߿ |
91Ʒþþþþio |
97Ʒ˾þô߽ |
ľþþƷ |
þþ뾫Ʒպ˳ |
97Ƶþþ |
˾ƷþѶ |
ݺɫݺݺݺݺɫۺϾþ |
ɫۺϾþɫ |
þ99Ʒ |
ĻþþƷ |
þˬˬ |
ŮдþӰԺ |
˾þô߽ۺվ |
ۺϾþþƷ |
MM131Ůþ |
ۺϾþһ |
þ¾Ʒ |
ŷսþþþþþþ |
þۺϾɫۺϾƷ |
ŷպľþ |
þƵᆱƷ99㽶 |
þþþƷҰ |
26uuuþ |
þþƷ99þ㽶ɫ |
һһþaaۺϾƷ
|
þùƷ77777 |
ٸþĻ |
ഺþ |