寻找C风格强制类型转换的工具

35

有没有工具可用于查找代码中的显式C样式强制类型转换?我正在重构一些C++代码,并希望尽可能替换C样式的强制类型转换。

一个示例的C样式强制类型转换:

Foo foo = (Foo) bar;

相反,C++样式转换的例子包括:

Foo foo = static_cast<Foo>(bar);
Foo foo = reinterpret_cast<Foo>(bar);
Foo foo = const_cast<Foo>(bar);

1
一个括号中的类型,例如:(int)f - AshleysBrain
哦,好的 - 他在对比C++风格。我对C++几乎一无所知,除了我对C的了解。 - Matt Ball
9个回答

37

如果您正在使用gcc/g++,只需启用C-style转换警告:

g++ -Wold-style-cast ...

5
在处理工作时,使用最好的工具和最简单的方法...如果可行的话。 - Hamish Grubijan
2
https://developercommunity.visualstudio.com/idea/550695/add-compile-option-to-warn-on-c-style-cast-usage.html - MrTux

9

搜索正则表达式 \)\w 可以得到出乎意料的好结果。


4
只有在将类型说明符放在变量旁边时,这个方法才能运行……你应该总是这样做,但并不是每个人都这么做。 - Platinum Azure
1
我一直在使用\(\w+ ?\*?\) ?\w,但要注意误报。 - Marc.2377
1
发现这个更有用:(?<!版权 )\(\w+ ?\*?\) ?\w - Marc.2377

8
这种类型的强制转换难以搜索,这也是引入新风格强制转换的原因之一。如果您的代码可以正常工作,那么这似乎是一个毫无意义的重构 - 我会在修改周围代码时将它们简单地更改为新风格的强制转换。
话虽如此,在C++代码中使用C风格的强制转换表明代码存在问题,应该进行修复 - 即使可能进行全局替换,我也不会这样做。

1
我必须遵守编码准则 :) - waffleman
大多数指南适用于新编写的代码。只有在需要进行更改时,才会对旧代码进行重构,例如修复bug。仅仅为了重构而重构只会浪费时间(和金钱),没有任何好处。 - RvdK
+1 当您在处理/重构周围的代码(并且预计重新测试)时,请修复它们。 - Mark B
3
只要没有人“看到”这些演员阵容不符合你的指南,就不会有人反对它们。因此,当你(或其他人)发现它们时,请进行修正。主动寻找它们似乎是浪费时间。只要不写出“更多”的这样的阵容,而在注意到时将旧的演员阵容进行修正即可。 - jalf

6

Offload C++ compiler 支持选项以将所有此类转换报告为编译时错误,并将此类转换的语义限制为与 static_cast 更安全的等价形式。

相关选项如下:

-cp_nocstylecasts   

编译器会在所有C风格的转换中发出错误。在C++代码中,C风格的转换可能不安全,并导致不希望或未定义的行为(例如将指针强制转换为不相关的结构体/类类型)。此选项对于重构非常有用,可以查找所有这些转换并将它们替换为更安全的C++转换,如static_cast。
-cp_c2staticcasts   

编译器将更严格的C++ static_cast语义应用于C风格的转换。打开此选项编译代码可确保C风格的转换至少与C++ static_cast一样安全。如果现有代码存在大量C风格转换,并且重构每个转换为C++转换需要付出太多努力,则此选项非常有用。

哦,不错!这次是一个真正的解析器 :) - Matthieu M.

1

一款能够准确分析C++源代码并进行自动化定制更改(例如,您的强制类型转换替换)的工具是DMS软件重构工具包

DMS拥有完整的C++解析器,构建AST和符号表,因此可以浏览您的代码以可靠地查找C样式强制类型转换。通过使用模式导向匹配和重写,您可以提供一组规则,将所有这些C样式强制类型转换转换为所需的C++等效项。

DMS已被用于进行波音和通用动力公司的大规模自动化C++重构任务,每个任务涉及数千个文件。


8
当您推销自己的产品时,应该事先明确说明。 - Matthew Flaschen

0

我已经回答过一次,提供了一个工具的描述,如果你愿意,它可以找到并 更改 所有的强制类型转换。

如果你只想 查找 这样的强制类型转换,还有另一个工具可以轻松地完成这个任务,事实上,它是所有“正则表达式”建议的极端泛化。那就是 SD Source Code Search Engine。这个工具可以让你按照语言元素搜索大型代码库。它提供了一个GUI,允许你输入查询,查看单个命中,通过一次鼠标点击显示命中点处的文件文本。再点击一下,你就可以进入你的编辑器[对于许多编辑器]打开文件。该工具还会记录一个带上下文的命中列表,以便稍后重新访问。

在你的情况下,以下搜索引擎查询可能会得到大部分强制类型转换:

'(' I ')'  | '(' I ... '*' ')'

这意味着,找到一个令牌序列,第一个是 (,第二个是任何标识符,第三个是 ')',或者涉及以 '*' 结尾的内容的类似序列。

您不需要指定任何空格管理,因为该工具了解语言的空格规则;它甚至会忽略转换中间的注释并仍然匹配上述内容。

[我是提供此工具的公司的首席技术官。]


0
C风格转换的一个问题在于,它们依赖于括号,而括号负荷过多,所以很难被注意到。然而,正则表达式(例如Python语法中的)可以识别这种转换方式。
r'\(\s*\w+\s*\)'

这是一个开始——它将带有括号内可选空格的单个标识符进行匹配。但是,当然无法捕获例如(void*)的强制转换——为了获取尾随的星号,

r'\(\s*\w+[\s*]*\)'

你也可以从可选的const开始,进一步扩大范围,等等。

一旦你有了一个好的正则表达式,许多工具(从grepvim,从awksed,以及perlpythonruby等)都可以让你将其应用于识别源代码中所有匹配项。


0

如果您使用某种匈牙利命名法(例如iIntegerpPointer等),那么您可以搜索例如)p) p等。

即使对于大型代码库,也应该能够在合理的时间内找到所有这些位置。


-1

我在Visual Studio(2010)的“查找文件”搜索框中使用了这个正则表达式::i\):i

感谢sth的灵感(他的帖子


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接