我想从C文件中删除未使用的局部变量。 例如:
int fun(int a , int b)
{
int c,sum=0;
sum=a + b;
return sum;
}
这里未使用的变量是'c'。
我将在外部列出所有未使用的局部变量。现在使用我所拥有的未使用的局部变量,我们必须从源代码和放大器中找到局部变量。删除。
在上面的例子中,“c”是未使用的变量。我会知道它(我有代码)。
在这里,我必须找到c&删除它。
修改
关键是不要使用外部工具查找未使用的局部变量。关键是要从列表中删除它们。
答案 0 :(得分:21)
调高编译器警告级别,它应该告诉你。
将源片段放在“f.c”中:
% gcc -c -Wall f.c
f.c: In function 'fun':
f.c:1: warning: unused variable 'c'
答案 1 :(得分:10)
整蛊 - 你必须为此解析C代码。结果有多接近? 我的意思是:
int a, /* foo */
b, /* << the unused one */
c; /* bar */
现在,人们很明显第二条评论必须要去。
轻微变化:
void test(/* in */ int a, /* unused */ int b, /* out */ int* c);
同样,第二条评论必须去,这次是b之前的评论。
通常,您希望解析输入,过滤它,并发出不是未使用变量声明的所有内容。您的解析器必须保留注释和#include语句,但如果您没有#include标头,则可能无法识别声明(如果使用宏来隐藏声明,则更是如此)。毕竟,你需要标题来决定是否A * B();是函数声明(当A是类型时)或乘法(当A是变量时)
[edit]此外:
即使您知道变量未使用,删除它的正确方法也很大程度上取决于远程上下文。例如,假设
int foo(int a, int b, int c) { return a + b; }
显然,c未被使用。你能把它改成吗?
int foo(int a, int b) { return a + b; }
也许,但不是如果&amp; foo存储在int(*)(int,int,int)
中。这可能发生在其他地方。如果(且仅当)发生这种情况,您应该将其更改为
int foo(int a, int b, int /*unused*/ ) { return a + b; }
答案 2 :(得分:5)
你为什么要这样做?假设您有一个不错的优化编译器(GCC,Visual Studio等),二进制输出将与您删除原始示例中的'int c'不同。
如果这只是代码清理,任何最新的IDE都会为您提供每个警告的源代码的快速链接,只需单击并删除:)
答案 3 :(得分:5)
我的回答更多是对MSalters非常彻底的回答的精心评论。 我会超越'棘手',并说这样的工具既不可能也不可取。
如果您只想删除对变量的引用,那么您可以编写自己的代码解析器,但是需要区分它所在的函数上下文,例如
int foo(double a, double b)
{
b = 10.0;
return (int) b;
}
int bar(double a, double b)
{
a = 5.00;
return (int) a;
}
任何简单的解析器都会遇到麻烦,'a'和'b'都是未使用的变量。
其次,如果您将评论视为MSalter,您会发现人们不会持续评论;
double a;
/*a is designed as a dummy variable*/
double b;
/*a is designed as a dummy variable*/
double a;
double b;
double a; /*a is designed as a dummy variable*/
double b;
等。
因此,简单地删除未使用的变量将创建孤立的评论,这可能比not commenting at all更危险。
最终,优雅地执行是一项非常困难的任务,无论如何你都会破坏代码。通过自动化流程,您可能会使代码变得更糟。
最后,您应该首先考虑变量在代码中的原因,如果它们被弃用,为什么在所有引用都没有删除它们时。
答案 4 :(得分:1)
答案 5 :(得分:1)
除了能够通过警告显示这些内容之外,如果打开任何优化,编译器通常会优化这些。检查变量是否从未被引用在编译器中的实现方面是非常简单的。
答案 6 :(得分:0)
你需要一个好的解析器来保留令牌的原始角色位置(即使存在预处理器!)。有一些自动重构C / C ++的工具,但它们远非主流。
我建议你查看Taras' Blog。这家伙正在做一些Mozilla代码库的大型自动重构,比如用返回值替换out-params。他重写代码的主要工具是Pork:
Pork是一个C ++解析和重写 工具链。 Pork的核心是C ++ 提供精确字符的解析器 开始和结束的位置 每个AST节点,以及一组 包含any的宏扩展 地点。这个信息允许C ++ 要自动重写 精确的方式。
来自博客:
到目前为止猪肉已被用于“未成年人” 比如重命名 课程和功能,旋转 outparameters和纠正prbool 错误。此外,Pork证明了自己 在涉及的实验中 重写几乎所有功能(即 在Mozilla中生成3 + MB补丁 使用垃圾收集代替 引用计数。
适用于C ++,但它可能适合您的需求。
答案 7 :(得分:0)
上面的一张海报上写着“不可能和不可取”。 另一个说“棘手”,这是正确的答案。 你需要1)一个完整的C(或任何感兴趣的语言)解析器, 2)理解语言的推理程序 标识符引用和数据流以确定变量 确实是“死”,3)实际修改的能力 源代码。
所有这些都很难建立的巨大能量 1)2)3)。您不能为任何单独的清理任务辩护。 人们可以做的是专门建立这样的基础设施 目标是在很多不同的方面分摊它 程序分析和转换任务。
我公司提供这样的工具:DMS软件再造 工具包。看到 http://www.semdesigns.com/Products/DMS/DMSToolkit.html DMS具有多种语言的生产质量前端, 包括C,C ++,Java和COBOL。
事实上,我们已经建立了一个自动化的“查找无用的声明” Java工具做两件事: a)将它们全部列出(从而生成列表!) b)使用无用的声明制作代码的副本 除去。 您可以选择要保留的答案: - )
为C做同样的事情并不困难。我们已经 有一个工具可以识别这些死变量/函数。
我们没有加入的一个案例是“无用的参数” case,因为删除了一个无用的参数,你有 找到来自其他模块的所有调用, 验证设置参数没有侧面 效果,并撕掉无用的论点。 事实上,我们有完整的软件图表 感兴趣的系统,所以这也是 可能的。
所以,它只是棘手,甚至不是很棘手 如果你有合适的基础设施。
答案 8 :(得分:-1)
另外:splint。
Splint是一种用于静态检查C程序是否存在安全漏洞和编码错误的工具。只需很少的努力,Splint可以用作更好的棉绒。如果投入额外的工作为程序添加注释,Splint可以执行比任何标准lint更强的检查。
答案 9 :(得分:-1)
您可以将问题解决为文本处理问题。必须有少量的正则表达式模式,如何在源代码中定义未使用的局部变量。
使用未使用的变量名称列表及其所在的行号,您可以逐行处理C源代码。在每一行上您可以迭代变量名称。在每个变量名称上您可以逐个匹配模式。成功匹配后您知道定义的语法,因此您知道如何从中删除未使用的变量。
例如,如果源行是:“int a,unused,b;”并且编译器将“未使用”报告为该行中未使用的变量,而模式“/,unused,/”将匹配,您可以用单个“,”替换该子字符串。