标签 Programmer 下的文章

多行宏定义中的注释问题

早上在写代码时遇到这样一个问题:即如何在一个拥有多行的宏定义中做注释?,这里把方法演化的过程贴出来,可能对某些朋友有些借鉴意义。

宏定义高深莫测,而且是比较细节的东西,详细说明请参见"C参考手册"之类的书籍。

在我的代码中,我大致要做这样一个简单的事情:printf("%s%s%s\n", "hello", "macro", "yeah!"); "%s%s%s\n"这个字符串中每一项输出都有一定的含义,而且在真实代码里,这个串中的输出项可不止3个,所以一个直接的想法就是将其定义为一个宏。

#define STR_OUTPUT_FORMAT_V0  "%s%s%s\n"
printf(STR_OUTPUT_FORMAT_V0, "hello ", "macro, ", "yeah!");
程序输出:hello macro, yeah!

由于真实代码中这个串很长,所以打算美化一下格式,定义成下面的样子:
#define STR_OUTPUT_FORMAT_V1  "%s\
                               %s\
                               %s\n"
printf(STR_OUTPUT_FORMAT_V1, "hello ", "macro, ", "yeah!");
程序输出:hello                                macro,                                yeah!

这样的定义显然不对,也在我意料之中,续行符将空格也续到格式串中了,导致输出的结果中带有大量空格。

改进一下,利用C语言的字符串自动连接语法。
#define STR_OUTPUT_FORMAT_V2  "%s"\
                              "%s"\
                              "%s\n"
printf(STR_OUTPUT_FORMAT_V2, "hello ", "macro, ", "yeah!");
程序输出:hello macro, yeah!

现在的问题是如何在这样一个多行的宏定义里加入注释,字段含义特殊,加上注释有利于以后维护以及别人阅读你的代码,否则一堆%s%s,让人看了就头痛。先这么加试试:
#define STR_OUTPUT_FORMAT_E1  "%s"\   /* comment1 */
                              "%s"\   /* comment2 */
                              "%s\n"  /* comment3 */
printf(STR_OUTPUT_FORMAT_E1, "hello ", "macro, ", "yeah!");
我们得到的结果:编译错误。
通过gcc -E 选项我们看到,宏替换后的代码:
                              "%s"\
                              "%s\n"
int main() {
        printf("%s"\, "hello ", "macro, ", "yeah!");
}

由于没有续行符在注释前面,所以宏定义的后两行实际上并没有被包含在宏定义中,就像没有暂住证的人一样,被GCC这个"警察"逮个正着。

继续改进:
#define STR_OUTPUT_FORMAT_V3  "%s"   /* comment1 */ \
                              "%s"   /* comment2 */ \
                              "%s\n"  /* comment3 */
printf(STR_OUTPUT_FORMAT_V3, "hello ", "macro, ", "yeah!");
程序输出:hello macro, yeah!
显然预编译器忽略宏定义中的注释以及空格,STR_OUTPUT_FORMAT_V3就完全符合我的要求了。

当然,很多人不建议使用宏,特别是C++的Fans,宏也的确有很多弊端,这里也有替代方法:
const char *str_output_format = "%s"    /* comment1 */
                                 "%s"    /* comment2 */
                                 "%s\n"; /* comment3 */
printf(str_output_format, "hello ", "macro, ", "yeah!");
程序输出:hello macro, yeah!

用一个字符串变量代替格式宏,还可以避免上述由于在宏中做注释带来的一系列问题。

使用Ubuntu工作了一上午

在公司里面,Windows还是一统天下的。人们已经熟悉了Windows上的各种软件和使用方法,特别是一些常用的配置管理工具,我们用的都是微软的产品,譬如Visual Source Safe,这给转到Ubuntu带来了一些麻烦,Ubuntu下虽然有Wine这个好工具,但是对于复杂的Windows软件来说,Wine的支持还是难以满足需求的。

在家里的时候一直都是用无线路由器上网的,开机登录桌面后无线就自动连接上了,所以我也一直没有配置过有线网络。在公司里一般都是DHCP或者静态IP分配的。我们这用的是后者,这就需要对Ubuntu进行静态IP分配。从"Beginning Ubuntu Linux "一书中找到了相关的设置方式(P116),System -> Administration -> Networking,在弹开的对话框中选择Wired connection,点击其Properties,设置IP和DNS。Ubuntu的网络设置生效方式很特殊,先去掉Wired connection前面的选择框,然后recheck这个选择框,这样Ubuntu就会重新激活这个网络配置,我就因为不了解这个走了很长时间弯路。

公司一般都会有http访问代理,我在firefox代理配置时必须选择"自动代理配置"才能访问网络,否则使用"手动代理配置"总是无法访问,奇怪的很。

Ubuntu的软件都是使用apt-get install的,我们在使用代理的网络里也需要给apt-get设置代理,这个在官方Wiki有说明,最简单的方式就是在需要安装软件的时候临时设置一个环境变量,以防更换网络配置时还需要到配置文件中修改代理设置。在你的一个终端窗口(Alt+F2, 输入gnome-terminal打开此窗口)输入:export http_proxy=http://username:passwd@proxyipaddr:port,如果你的网络环境不是总变化的话,可以将其放入.bashrc中。

公司的网络不知为什么访问Ubuntu的几个源服务器还是蛮快的,装Subversionruby就用了不到几分钟,如果是在家里,那半个小时也搞不定,铁通的网络真的不咋的。

就这样,一上午都一直在用Ubuntu编码,直到下午要回复一封重要的mail,才换回Windows,没办法,邮件都在outlook里呢。

用Ubuntu时间不长,但是也感觉到了Linux的GUI界面的反应灵敏度的确逊色于Windows,昨天GF在Ubuntu下玩在线Flash游戏时就一直向我抱怨这是什么’破系统’,但不知者不乖,毕竟Linux使用的是X-Windows,不像Windows将GUI做到内核里去了,反应慢也是情有可原的,能理解。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats