news 2026/5/2 3:23:01

C语言对话-24.好的,坏的,不赞成的

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言对话-24.好的,坏的,不赞成的

sebastian 翻译

关于我第一次程序设计工作的可笑事(这是很多年以后,我在与我的新婚妻子珍妮喝早茶时谈起的。)是鲍勃如何死皮赖脸地不想离职,尽管他根本无法胜任。我记得一个很特别的天气晴朗春天的早晨....

当时我正在努力地完成一段新代码。这时鲍勃逛到了我的工作隔间,依在隔间的墙上,喝了一口咖啡。--不,我不知道他手上为什么总是有一杯咖啡,鲍勃站在那里微笑的说:"嗨!菜鸟。”

我漫不经心的说:“嗨,鲍勃,什么事?”

“这段代码你上周检查过了吗?”他耸耸肩,“好,它破坏了整体结构。编译器说你定义了Output函数两次,你不能这样做。”

“什么?”我诧异的说:“但是,我肯定我已经生成了……”我快速的把我一周前做的文件调入了编辑器:

//--- file trans.cpp -----------------------------

//

static void Output( ostream& o ) { /*...*/ }

// ...

void ProcessTransaction( /*...*/ )

{

// ...

Output( cout );

// ...

}

“这些,不是很好吗,”我说道,坐了回去,心里很满意,看来鲍勃完全是无中生有。

鲍勃笑了笑。“继续看下去。”他催促道。

我皱了皱眉,用grep扫描了源代码。期望发现Output函数在同一模块中是否还出现在其他什么地方。另人惊讶的是,我在另3个文件里发现了它。

//--- file output.h ------------------------------

void Output( std::ostream& );

//--- file output.cpp ----------------------------

#include "output.h"

// ...

void Output( ostream& out ) { /*...*/ }

//--- file dbinit.cpp ----------------------------

//

#include "output.h"

// ...

void InitDatabase()

{

// ...

Output( clog );

// ...

}

我沉思了一下。“但是,这是同一个Output函数吗?”我问道。

鲍勃不耐烦的用拿着咖啡杯的手比划了一下,"你刚才没听我说吗?我刚才告诉你了你写的代码。无法正常生成。"

“生成什么?”

“就在我们的嵌入式目标平台上,至少我看到生成器抱怨无法生成。修正它,弄完后告诉我一起,我可以接下去干。”鲍勃呷了一口咖啡,叫了几声,然后离开了。

好了,我老实承认:一开始我并不相信鲍勃的话。

我试着用我们一直用的编译器,重新生成,一切正常。我受到鼓舞,更换了Shell,用我们用于嵌入式目标的编译器重成生成,结果无法生成。我呆了下来,喃喃自语:我用的第一个编译器允许两个Output函数共存,但另外一个编译器却抱怨说存在重复的定义,尽管前后两个是同一段代码。

我打算放弃了,并去向温迪求教时,我听到了我身后传来了一阵飒飒的翻书声,这时一声合上书的声音从我身后传来:“需要帮助吗?"Guru的声音从我后面传来了:“你好像遇到了什么难题了,需要我帮忙吗?”

我转过来看到她在微笑,“当然,”我很高兴有人来帮我,“这是我写的代码,这里是编译器反映的错误,我到底错在哪里了?”

她快速的扫视了一遍代码和编译结果。“哦,”她说,“这里有两个问题,但是我们以前已经讨论研究过了这个问题,你认为发生了什么事?你尽所能解释一下发生了什么。”

我接受了挑战:“好的,对...一个是在trans.cpp中,我希望在ProcessTans中调用Output是那个静态版本的Output。”

“还有呢?”她催促道。

“另一方面,在dbinit.cpp中,我希望在InitDatabase中对Output的调用将会是外部定义的Output,存在于output.cpp。”

“但是...?”她又催促道。

“值得注意的是,我们的主要编译器看来同意我的做法,否则的话,我在代码上交前就应该发现问题。但另一个编译器却不允许这样做。”

“做的很好,”Guru平静的说,“现在沉思一下你所看到的东西,你将发现这里的确有两个很明显的问题,第一个问题是嵌入式编译器出错了,很明显你的的代码是合法的,而我们主要使用的编译器确实对这段代码进行了正确的处理。一个函数如果是被声明为static的话,仅仅是做内部连接,也就是说,根据概念3:5第三段的标准来的,但是其他的output是进行外部连接的,依据概念3:5第九段,它和trans.cpp内的静态版本的Output不是同一个函数,这就是说为什么嵌入式编译器出错,无法正确辨认出两个Output,这是两个截然不同的函数,而不是一个。”

“原来如此,”我放心的说,“酷,这下子我懂了。”

“你肯定吗?第二个问题是,”Guru继续说,“尽管你代码是合法的,但是它并不遵守我们的编码标准。”

“什么?我使用了正确的对齐和缩进啊。”

Guru退了一步,紧紧闭住眼睛,并挥手示意我安静。“不,不,不,不。没有哪种编码标准值得你浪费时间这样定义东西,包括我们。除了,当然,嵌入表是有害的,不管是用哪种形式的使用空格的缩进。不,你可能看的是鲍勃在他以前工作时带来的标准,但这些东西现在并不适用。”

“还有,”她继续道,“问题是你对static的使用,你这种static的使用方法是老式的、陈旧的、不提倡使用的,而且大多数都被认为是有缺陷的。”。她打开了她的书,现在我知道那是Stroustrup的The C++ Programming Language [1],找出一处临近书尾的地方,引述道:“用static来表示‘本地于编译单位’在C++中是不被提倡的...”她透过了眼镜看了看我,继续引述,“用无名的名字空间来代替。”

我灵机一动,“哦,我知道该怎么做了”,我改正了代码:

//--- file trans.cpp -----------------------------

//

namespace

{

void Output( ostream& o ) { /*...*/ }

}

// ...

void ProcessTransaction( /*...*/ )

{

// ...

Output( cout );

// ...

}

“当然,我的徒弟,我现在确实相信我们过时的嵌入式编译器可以正确的处理你修订过的代码。”声音渐渐的消失,我转过身去发现Guru已经不见了,就像她来的时候。

我笑了笑,活动了一下指关节,成功的重写了代码,并通过了所有的编译器编译,和单元测试,并呈交了代码。我微笑的打开了email,给鲍勃发了一封简短而又含糊其词的通知。

[参考文献]

[1] Bjarne Stroustrup. The C++ Programming Language, 3rd Edition (Addison-Wesley, 1997).

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:22:34

计算机毕业设计springboot南江实验中学教务管理系统 基于 SpringBoot 的南江实验中学教务管理平台的设计与实现南江实验中学教务信息管理系统的开发 ——SpringBoot 框架应用

计算机毕业设计springboot南江实验中学教务管理系统o552t98o (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。在教育数字化转型的大趋势下,传统教务管理模式的效率低下…

作者头像 李华
网站建设 2026/4/23 15:15:22

DataFrame和 Series 索引

索引 df.indexIndex([1001, 1000, 1002, 1003], dtypeint64)df.columns.name "properties"df.rename(columns{"name":"First Name","age":"Age"})

作者头像 李华
网站建设 2026/4/21 8:11:32

大模型推理场景下的 AI 网关:定位、职责与架构演进

引言 从 2025 年初开始,大模型领域进入了新一轮加速发展阶段。随着大模型在企业内部系统和生产环境中的落地,大模型推理逐渐演化为一类重要的基础设施能力。在这一背景下,围绕大模型推理访问、资源管理与安全控制的 AI 网关(AI Gateway) 受到了业界的广泛关注(参见参考资…

作者头像 李华