如果0在c程序中编译
if 0 is compiled in c program
我正在尝试从我的程序中删除未使用的代码 - 我现在无法删除代码,我只想先禁用它。
假设我有以下代码:
if (cond){
doSomething()
}
和 cond
始终为假,因此永远不会调用 doSomething
。
我想做类似的事情:
#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
doSomething()
}
现在这对我们(希望对编译器)来说很明显,这段代码未被使用。
编译器会删除所有这些 if
条件,还是会留下它永远不会进入?
P.S.: 我不能将 #if 0
用于此目的
查看您的这段代码
#define REMOVE_UNUSED_CODE 0
if(cond && REMOVE_UNUSED_CODE)
{
doSomething();
}
REMOVE_UNUSED_CODE
在编译前被预处理器替换为 0
。
因此 if(cond && 0)
将始终被评估为 false 并且永远不会被执行。所以你可以说,不管 cond
是什么,它总是假的。
所以我更喜欢这样做:
//#define REMOVE_UNUSED_CODE 0
#ifdef REMOVE_UNUSED_CODE
if(cond)
{
doSomething();
}
#endif
答案取决于编译器的实现。你永远不应该依赖这个。
而是明确:
#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
#ifndef REMOVE_UNUSED_CODE
doSomething()
#endif
}
尝试
#ifndef REMOVE_UNUSED_CODE
if (cond) {
doSomething();
}
#endif
相反。
别忘了做一个
#define REMOVE_UNUSED_CODE
某处。
你不应该那样做:
假设你有一个函数 bool f(void* input)
有副作用。
然后
if( f(pointer) && false ) { ... }
正文未评价,但f
应该
在
的情况下
if( false && f(pointer) ) { ... }
由于 &&
运算符的快捷规则,f 未被计算。
如果你使用
#define REMOVE_UNUSED_CODE
#ifndef REMOVE_UNUSED_CODE
if( f(pointer) && false ) { }
#endif
整个代码甚至没有编译进去,也永远不会执行。
GCC 将显式删除具有控制它们的常量表达式的条件块,并且 the GNU coding standards explicitly recommend that you take advantage of this,而不是使用更粗糙的方法,例如依赖预处理器。尽管使用预处理器 #if
可能看起来更有效,因为它在早期阶段删除了代码,但实际上,现代优化器在您为它们提供尽可能多的信息时效果最好(当然,如果您可以避免在不需要的地方添加相分离依赖。
像这样的决定对于现代编译器来说非常、非常 - 即使是非常简单的 TCC will perform some amount of dead-code elimination; powerful systems like LLVM 和 GCC 也会发现这一点,而且要复杂得多作为人类,您 reader 可能会错过的案例(通过跟踪变量的生命周期和修改,而不是简单地查看单个点)。
这是对完全编译的其他优点的补充,例如 if
中的代码将被检查是否有错误(而 #if
对于删除 在您当前的系统上会错误,例如引用不存在的平台功能)。
不是直接的答案,但可能会有帮助。有特定于编译器的内部函数来执行代码删除。
对于 MSVC,它是 __assume(0)
对于GCC/Clang,是__builtin_unreachable()
。
但是请注意,如果您这样写:
if (cond){
__builtin_unreachable();
doSomething()
}
您的条件永远不应计算为 true
,否则行为未定义。
结合 && REMOVE_UNUSED_CODE
和 __builtin_unreachable()
确保您的代码将被编译器删除。
我正在尝试从我的程序中删除未使用的代码 - 我现在无法删除代码,我只想先禁用它。
假设我有以下代码:
if (cond){
doSomething()
}
和 cond
始终为假,因此永远不会调用 doSomething
。
我想做类似的事情:
#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
doSomething()
}
现在这对我们(希望对编译器)来说很明显,这段代码未被使用。
编译器会删除所有这些 if
条件,还是会留下它永远不会进入?
P.S.: 我不能将 #if 0
用于此目的
查看您的这段代码
#define REMOVE_UNUSED_CODE 0
if(cond && REMOVE_UNUSED_CODE)
{
doSomething();
}
REMOVE_UNUSED_CODE
在编译前被预处理器替换为 0
。
因此 if(cond && 0)
将始终被评估为 false 并且永远不会被执行。所以你可以说,不管 cond
是什么,它总是假的。
所以我更喜欢这样做:
//#define REMOVE_UNUSED_CODE 0
#ifdef REMOVE_UNUSED_CODE
if(cond)
{
doSomething();
}
#endif
答案取决于编译器的实现。你永远不应该依赖这个。
而是明确:
#define REMOVE_UNUSED_CODE 0
if (cond && REMOVE_UNUSED_CODE){
#ifndef REMOVE_UNUSED_CODE
doSomething()
#endif
}
尝试
#ifndef REMOVE_UNUSED_CODE
if (cond) {
doSomething();
}
#endif
相反。 别忘了做一个
#define REMOVE_UNUSED_CODE
某处。
你不应该那样做:
假设你有一个函数 bool f(void* input)
有副作用。
然后
if( f(pointer) && false ) { ... }
正文未评价,但f
应该
在
的情况下if( false && f(pointer) ) { ... }
由于 &&
运算符的快捷规则,f 未被计算。
如果你使用
#define REMOVE_UNUSED_CODE
#ifndef REMOVE_UNUSED_CODE
if( f(pointer) && false ) { }
#endif
整个代码甚至没有编译进去,也永远不会执行。
GCC 将显式删除具有控制它们的常量表达式的条件块,并且 the GNU coding standards explicitly recommend that you take advantage of this,而不是使用更粗糙的方法,例如依赖预处理器。尽管使用预处理器 #if
可能看起来更有效,因为它在早期阶段删除了代码,但实际上,现代优化器在您为它们提供尽可能多的信息时效果最好(当然,如果您可以避免在不需要的地方添加相分离依赖。
像这样的决定对于现代编译器来说非常、非常 - 即使是非常简单的 TCC will perform some amount of dead-code elimination; powerful systems like LLVM 和 GCC 也会发现这一点,而且要复杂得多作为人类,您 reader 可能会错过的案例(通过跟踪变量的生命周期和修改,而不是简单地查看单个点)。
这是对完全编译的其他优点的补充,例如 if
中的代码将被检查是否有错误(而 #if
对于删除 在您当前的系统上会错误,例如引用不存在的平台功能)。
不是直接的答案,但可能会有帮助。有特定于编译器的内部函数来执行代码删除。
对于 MSVC,它是 __assume(0)
对于GCC/Clang,是__builtin_unreachable()
。
但是请注意,如果您这样写:
if (cond){
__builtin_unreachable();
doSomething()
}
您的条件永远不应计算为 true
,否则行为未定义。
结合 && REMOVE_UNUSED_CODE
和 __builtin_unreachable()
确保您的代码将被编译器删除。